fix: preserve query params without values by not appending = sign (#7567)

* fix: preserve query params without values by not appending = sign

* fix: parseCurlCommand test
This commit is contained in:
Pooja
2026-04-01 20:08:31 +05:30
committed by GitHub
parent 9e89255f6d
commit 40298b96a4
3 changed files with 53 additions and 4 deletions

View File

@@ -902,7 +902,7 @@ describe('parseCurlCommand', () => {
{ name: 'test', value: 'urlquery' },
{ name: 'name', value: 'John%20Doe' },
{ name: 'email', value: 'john@example.com' },
{ name: 'hello', value: '' }
{ name: 'hello', value: undefined }
]
});
});

View File

@@ -50,6 +50,18 @@ describe('encodeUrl', () => {
expect(encodeUrl(url)).toBe(expected);
});
it('should handle query parameters without values (no = sign)', () => {
const url = 'https://example.com/api?flag&age=25&verbose';
const expected = 'https://example.com/api?flag&age=25&verbose';
expect(encodeUrl(url)).toBe(expected);
});
it('should handle mixed empty-value and no-value parameters', () => {
const url = 'https://example.com/api?seat=&table=2&flag';
const expected = 'https://example.com/api?seat=&table=2&flag';
expect(encodeUrl(url)).toBe(expected);
});
it('should encode query parameters with pipe operator', () => {
const url = 'https://example.com/api?filter=status|active&sort=name|asc&tags=frontend|backend|api';
const expected = 'https://example.com/api?filter=status%7Cactive&sort=name%7Casc&tags=frontend%7Cbackend%7Capi';
@@ -159,7 +171,7 @@ describe('parseQueryParams', () => {
expect(result).toEqual([]);
});
it('should handle query parameters with empty values', () => {
it('should handle query parameters with empty values (has = sign)', () => {
const queryString = 'name=&age=25&active=';
const result = parseQueryParams(queryString);
expect(result).toEqual([
@@ -169,6 +181,16 @@ describe('parseQueryParams', () => {
]);
});
it('should handle query parameters without values (no = sign)', () => {
const queryString = 'flag&age=25&verbose';
const result = parseQueryParams(queryString);
expect(result).toEqual([
{ name: 'flag', value: undefined },
{ name: 'age', value: '25' },
{ name: 'verbose', value: undefined }
]);
});
it('should extract query parameters with pipe operator', () => {
const queryString = 'filter=status|active&sort=name|asc&tags=frontend|backend';
const result = parseQueryParams(queryString);
@@ -218,4 +240,23 @@ describe('buildQueryString', () => {
const result = buildQueryString(params, { encode: false });
expect(result).toBe('filter=status|active&sort=name|asc');
});
it('should omit = for params with undefined value', () => {
const params = [
{ name: 'flag', value: undefined },
{ name: 'age', value: '25' },
{ name: 'verbose' }
];
const result = buildQueryString(params);
expect(result).toBe('flag&age=25&verbose');
});
it('should include = for params with empty string value', () => {
const params = [
{ name: 'seat', value: '' },
{ name: 'table', value: '2' }
];
const result = buildQueryString(params);
expect(result).toBe('seat=&table=2');
});
});

View File

@@ -16,8 +16,12 @@ function buildQueryString(paramsArray: QueryParam[], { encode = false }: BuildQu
.filter(({ name }) => typeof name === 'string' && name.trim().length > 0)
.map(({ name, value }) => {
const finalName = encode ? encodeURIComponent(name) : name;
const finalValue = encode ? encodeURIComponent(value ?? '') : (value ?? '');
if (value === undefined) {
return finalName;
}
const finalValue = encode ? encodeURIComponent(value) : value;
return `${finalName}=${finalValue}`;
})
.join('&');
@@ -39,9 +43,13 @@ function parseQueryParams(query: string, { decode = false }: ExtractQueryParamsO
return null;
}
// Distinguish between ?param (no '=' at all) and ?param= (has '=' with empty value)
const hasEqualsSign = pair.includes('=');
const value = hasEqualsSign ? (decode ? decodeURIComponent(valueParts.join('=')) : valueParts.join('=')) : undefined;
return {
name: decode ? decodeURIComponent(name) : name,
value: decode ? decodeURIComponent(valueParts.join('=')) : valueParts.join('=')
value
};
}).filter((param): param is NonNullable<typeof param> => param !== null);