Skip to content

Commit 88aa1d8

Browse files
johnoliverCopilot
andcommitted
Address code review feedback on pagination implementation
- Tighten rel regex with word boundary to prevent false positives (e.g., rel="nextsomething" no longer matches). - Use parsed.origin comparison in validatePaginationUrl to correctly handle explicit default ports (e.g., :443 for HTTPS). - Fix pagination safeguard tests to use same-origin URLs so they actually exercise the 1000-page limit instead of being rejected by origin validation on the first request. - Add test for rel="nextsomething" not matching. - Add test for explicit default port acceptance. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 284c50b commit 88aa1d8

5 files changed

Lines changed: 23 additions & 7 deletions

File tree

__tests__/distributors/adopt-installer.test.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,8 @@ describe('getAvailableVersions', () => {
170170
});
171171

172172
it('stops pagination after 1000 pages as a safeguard', async () => {
173-
const nextPageUrl = 'https://example.com/releases?page=2';
173+
const nextPageUrl =
174+
'https://api.adoptopenjdk.net/v3/assets/version/%5B1.0,100.0%5D?page=2&page_size=20';
174175
spyHttpClient.mockReturnValue({
175176
statusCode: 200,
176177
headers: {link: `<${nextPageUrl}>; rel="next"`},

__tests__/distributors/semeru-installer.test.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,8 @@ describe('getAvailableVersions', () => {
113113
});
114114

115115
it('stops pagination after 1000 pages as a safeguard', async () => {
116-
const nextPageUrl = 'https://example.com/releases?page=2';
116+
const nextPageUrl =
117+
'https://api.adoptopenjdk.net/v3/assets/version/%5B1.0,100.0%5D?page=2&page_size=20';
117118
spyHttpClient.mockReturnValue({
118119
statusCode: 200,
119120
headers: {link: `<${nextPageUrl}>; rel="next"`},

__tests__/distributors/temurin-installer.test.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,8 @@ describe('getAvailableVersions', () => {
127127
});
128128

129129
it('stops pagination after 1000 pages as a safeguard', async () => {
130-
const nextPageUrl = 'https://example.com/releases?page=2';
130+
const nextPageUrl =
131+
'https://api.adoptium.net/v3/assets/version/%5B1.0,100.0%5D?page=2&page_size=20';
131132
spyHttpClient.mockReturnValue({
132133
statusCode: 200,
133134
headers: {link: `<${nextPageUrl}>; rel="next"`},

__tests__/util.test.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,10 @@ describe('getNextPageUrlFromLinkHeader', () => {
108108
'https://api.adoptium.net/v3/versions?page=3'
109109
],
110110
[{link: '<https://example.com/last?page=5>; rel="last"'}, null],
111+
[
112+
{link: '<https://example.com/page?p=2>; rel="nextsomething"'},
113+
null
114+
],
111115
[undefined, null]
112116
])('returns %s -> %s', (headers, expected) => {
113117
expect(getNextPageUrlFromLinkHeader(headers)).toBe(expected);
@@ -147,6 +151,15 @@ describe('validatePaginationUrl', () => {
147151
validatePaginationUrl('not-a-url', 'https://api.adoptium.net')
148152
).toBe(false);
149153
});
154+
155+
it('accepts URL with explicit default port', () => {
156+
expect(
157+
validatePaginationUrl(
158+
'https://api.adoptium.net:443/v3/assets?page=2',
159+
'https://api.adoptium.net'
160+
)
161+
).toBe(true);
162+
});
150163
});
151164

152165
describe('getVersionFromFileContent', () => {

src/util.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,9 @@ export function getNextPageUrlFromLinkHeader(
227227
if (!urlMatch) continue;
228228

229229
const params = linkValue.slice(urlMatch[0].length);
230-
if (/;\s*rel="?next"?/i.test(params)) {
230+
// Use word boundary to match "next" as a standalone relation type
231+
// RFC 8288 allows space-separated relation types like rel="next prev"
232+
if (/;\s*rel="?[^"]*\bnext\b/i.test(params)) {
231233
return urlMatch[1];
232234
}
233235
}
@@ -242,9 +244,7 @@ export function validatePaginationUrl(
242244
try {
243245
const parsed = new URL(url);
244246
const allowed = new URL(allowedOrigin);
245-
return (
246-
parsed.protocol === allowed.protocol && parsed.host === allowed.host
247-
);
247+
return parsed.origin === allowed.origin;
248248
} catch {
249249
return false;
250250
}

0 commit comments

Comments
 (0)