Skip to content

Commit

Permalink
fix(query): remove undefined values
Browse files Browse the repository at this point in the history
Close #3276
  • Loading branch information
posva committed Aug 6, 2020
1 parent 982f334 commit b952573
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 30 deletions.
68 changes: 38 additions & 30 deletions src/util/query.js
Expand Up @@ -9,9 +9,10 @@ const commaRE = /%2C/g
// fixed encodeURIComponent which is more conformant to RFC3986:
// - escapes [!'()*]
// - preserve commas
const encode = str => encodeURIComponent(str)
.replace(encodeReserveRE, encodeReserveReplacer)
.replace(commaRE, ',')
const encode = str =>
encodeURIComponent(str)
.replace(encodeReserveRE, encodeReserveReplacer)
.replace(commaRE, ',')

const decode = decodeURIComponent

Expand All @@ -30,11 +31,15 @@ export function resolveQuery (
}
for (const key in extraQuery) {
const value = extraQuery[key]
parsedQuery[key] = Array.isArray(value) ? value.map(v => '' + v) : '' + value
parsedQuery[key] = Array.isArray(value)
? value.map(castQueryParamValue)
: castQueryParamValue(value)
}
return parsedQuery
}

const castQueryParamValue = value => (value == null ? value : '' + value)

function parseQuery (query: string): Dictionary<string> {
const res = {}

Expand All @@ -47,9 +52,7 @@ function parseQuery (query: string): Dictionary<string> {
query.split('&').forEach(param => {
const parts = param.replace(/\+/g, ' ').split('=')
const key = decode(parts.shift())
const val = parts.length > 0
? decode(parts.join('='))
: null
const val = parts.length > 0 ? decode(parts.join('=')) : null

if (res[key] === undefined) {
res[key] = val
Expand All @@ -64,33 +67,38 @@ function parseQuery (query: string): Dictionary<string> {
}

export function stringifyQuery (obj: Dictionary<string>): string {
const res = obj ? Object.keys(obj).map(key => {
const val = obj[key]

if (val === undefined) {
return ''
}
const res = obj
? Object.keys(obj)
.map(key => {
const val = obj[key]

if (val === null) {
return encode(key)
}
if (val === undefined) {
return ''
}

if (Array.isArray(val)) {
const result = []
val.forEach(val2 => {
if (val2 === undefined) {
return
if (val === null) {
return encode(key)
}
if (val2 === null) {
result.push(encode(key))
} else {
result.push(encode(key) + '=' + encode(val2))

if (Array.isArray(val)) {
const result = []
val.forEach(val2 => {
if (val2 === undefined) {
return
}
if (val2 === null) {
result.push(encode(key))
} else {
result.push(encode(key) + '=' + encode(val2))
}
})
return result.join('&')
}
})
return result.join('&')
}

return encode(key) + '=' + encode(val)
}).filter(x => x.length > 0).join('&') : null
return encode(key) + '=' + encode(val)
})
.filter(x => x.length > 0)
.join('&')
: null
return res ? `?${res}` : ''
}
11 changes: 11 additions & 0 deletions test/unit/specs/query.spec.js
Expand Up @@ -20,10 +20,21 @@ describe('Query utils', () => {
})
})

it('should keep undefined and null query values', () => {
const query = resolveQuery('', { a: undefined, b: null })
expect(query).toEqual({ a: undefined, b: null })
})

it('should keep null query values in arrays', () => {
const query = resolveQuery('', { baz: [null, '2'] })
expect(query).toEqual({ baz: [null, '2'] })
})

it('should cast query values into string', () => {
const query = resolveQuery('foo=bar&foo=k', { baz: 1 })
expect(query.baz).toBe('1')
})

it('should cast query array values into string', () => {
const query = resolveQuery('foo=bar&foo=k', { baz: [1, '2'] })
expect(query.baz).toEqual(['1', '2'])
Expand Down

0 comments on commit b952573

Please sign in to comment.