Skip to content

Fix duplicated searchParams for pagination API #1229

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -1178,7 +1178,7 @@ Options are deeply merged to a new object. The value of each key is determined a
- If the parent property is a plain `object`, the parent value is deeply cloned.
- Otherwise, `undefined` is used.
- If the parent value is an instance of `URLSearchParams`:
- If the new value is a `string`, an `object` or an instance of `URLSearchParams`, a new `URLSearchParams` instance is created. The values are merged using [`urlSearchParams.append(key, value)`](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams/append).
- If the new value is a `string`, an `object` or an instance of `URLSearchParams`, a new `URLSearchParams` instance is created. The values are merged using [`urlSearchParams.append(key, value)`](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams/append). The keys defined in the new value override the keys defined in the parent value.
- Otherwise, the only available value is `undefined`.
- If the new property is a plain `object`:
- If the parent property is a plain `object` too, both values are merged recursively into a new `object`.
Expand Down
9 changes: 7 additions & 2 deletions source/core/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -656,12 +656,17 @@ export default class Request extends Duplex implements RequestEvents<Request> {
validateSearchParameters(options.searchParams);
}

options.searchParams = new URLSearchParams(options.searchParams as Record<string, string>);
const searchParameters = new URLSearchParams(options.searchParams as Record<string, string>);

// `normalizeArguments()` is also used to merge options
defaults?.searchParams?.forEach((value, key) => {
(options!.searchParams as URLSearchParams).append(key, value);
// Only use default if one isn't already defined
if (!searchParameters.has(key)) {
searchParameters.append(key, value);
}
});

options.searchParams = searchParameters;
}
}

Expand Down
58 changes: 57 additions & 1 deletion test/pagination.ts
Original file line number Diff line number Diff line change
Expand Up @@ -531,7 +531,7 @@ test('next url in json response', withServer, async (t, server, got) => {
]);
});

test.failing('pagination using searchParams', withServer, async (t, server, got) => {
test('pagination using searchParams', withServer, async (t, server, got) => {
server.get('/', (request, response) => {
const parameters = new URLSearchParams(request.url.slice(2));
const page = Number(parameters.get('page') ?? 0);
Expand Down Expand Up @@ -580,3 +580,59 @@ test.failing('pagination using searchParams', withServer, async (t, server, got)
'/?page=3'
]);
});

test('pagination using extended searchParams', withServer, async (t, server, got) => {
server.get('/', (request, response) => {
const parameters = new URLSearchParams(request.url.slice(2));
const page = Number(parameters.get('page') ?? 0);

response.end(JSON.stringify({
currentUrl: request.url,
next: page < 3
}));
});

interface Page {
currentUrl: string;
next?: string;
}

const client = got.extend({
searchParams: {
limit: 10
}
});

const all = await client.paginate.all('', {
searchParams: {
page: 0
},
responseType: 'json',
pagination: {
transform: (response: Response<Page>) => {
return [response.body.currentUrl];
},
paginate: (response: Response<Page>) => {
const {next} = response.body;
const previousPage = Number(response.request.options.searchParams!.get('page'));

if (!next) {
return false;
}

return {
searchParams: {
page: previousPage + 1
}
};
}
}
});

t.deepEqual(all, [
'/?page=0&limit=10',
'/?page=1&limit=10',
'/?page=2&limit=10',
'/?page=3&limit=10'
]);
});