Commit 71e9385e authored by Robert Knight's avatar Robert Knight

Omit query params with `undefined` values from API calls

The previous version stated that it aimed to match the behavior of the
`query-string` package but it was actually tested against Node's
`querystring` package, which has slightly different behavior for this
edge case. It omits parameters with `undefined` values and renders empty
parameters for `null` values.

The notebook view was calling `api.search({ uri: undefined, ... })` and
this translated to `/api/search?uri=&...` which caused an error.

Omit parameters instead in this case.
parent 98f66222
......@@ -128,15 +128,18 @@ function createAPICall(
params
);
/** @param {Param?} param */
const serialize = param => param?.toString() ?? '';
const apiURL = new URL(url);
for (let [key, value] of Object.entries(queryParams)) {
if (Array.isArray(value)) {
value.forEach(v => apiURL.searchParams.append(key, serialize(v)));
} else {
apiURL.searchParams.append(key, serialize(value));
if (!Array.isArray(value)) {
value = [value];
}
for (let item of value) {
// eslint-disable-next-line eqeqeq
if (item == null) {
// Skip all parameters with nullish values.
continue;
}
apiURL.searchParams.append(key, item.toString());
}
}
......
......@@ -176,7 +176,7 @@ describe('APIService', () => {
// Test serialization of nullish parameters in API calls. This behavior matches
// the query-string package that we used to use.
it('sends empty query parameters if value is nullish', () => {
expectCall('get', 'search?a=&b=&c=false&d=');
expectCall('get', 'search?c=false');
return api.search({ a: undefined, b: null, c: false, d: [null] });
});
......
......@@ -7,19 +7,20 @@
* replaceURLParams('/things/:id', {id: 'foo', q: 'bar'}) =>
* {url: '/things/foo', unusedParams: {q: 'bar'}}
*
* @template Param
* @param {string} url
* @param {Record<string, string>} params
* @return {{ url: string, unusedParams: Record<string, string>}}
* @param {Record<string, Param>} params
* @return {{ url: string, unusedParams: Record<string, Param>}}
*/
export function replaceURLParams(url, params) {
/** @type {Record<string, string>} */
/** @type {Record<string, Param>} */
const unusedParams = {};
for (const param in params) {
if (params.hasOwnProperty(param)) {
const value = params[param];
const urlParam = ':' + param;
if (url.indexOf(urlParam) !== -1) {
url = url.replace(urlParam, encodeURIComponent(value));
url = url.replace(urlParam, encodeURIComponent(String(value)));
} else {
unusedParams[param] = value;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment