0
0
mirror of https://github.com/honojs/hono.git synced 2024-11-21 10:08:58 +01:00

refactor(request): use URLSearchParams for parsing query params

This commit is contained in:
Yusuke Wada 2024-10-27 16:57:04 +09:00
parent 7e11832526
commit 17146063de
2 changed files with 18 additions and 81 deletions

View File

@ -174,6 +174,7 @@ describe('url', () => {
expect(getQueryParam('http://example.com/?Hono+is=a+web+framework', 'Hono is')).toBe(
'a web framework'
)
expect(getQueryParam('http://example.com/?q=%h', 'q')).toBe('%h')
expect(getQueryParam('http://example.com/?name0=sam&name1=tom', 'name0')).toBe('sam')
expect(getQueryParam('http://example.com/?name0=sam&name1=tom', 'name1')).toBe('tom')

View File

@ -199,95 +199,31 @@ export const checkOptionalParameter = (path: string): string[] | null => {
return results.filter((v, i, a) => a.indexOf(v) === i)
}
// Optimized
const _decodeURI = (value: string) => {
if (!/[%+]/.test(value)) {
return value
}
if (value.indexOf('+') !== -1) {
value = value.replace(/\+/g, ' ')
}
return /%/.test(value) ? decodeURIComponent_(value) : value
}
const _getQueryParam = (
url: string,
key?: string,
multiple?: boolean
): string | undefined | Record<string, string> | string[] | Record<string, string[]> => {
let encoded
):
| string
| undefined
| string[]
| Record<string, string | undefined>
| Record<string, string[]> => {
const searchParams = new URLSearchParams(getQueryStrings(url))
if (!multiple && key && !/[%+]/.test(key)) {
// optimized for unencoded key
let keyIndex = url.indexOf(`?${key}`, 8)
if (keyIndex === -1) {
keyIndex = url.indexOf(`&${key}`, 8)
}
while (keyIndex !== -1) {
const trailingKeyCode = url.charCodeAt(keyIndex + key.length + 1)
if (trailingKeyCode === 61) {
const valueIndex = keyIndex + key.length + 2
const endIndex = url.indexOf('&', valueIndex)
return _decodeURI(url.slice(valueIndex, endIndex === -1 ? undefined : endIndex))
} else if (trailingKeyCode == 38 || isNaN(trailingKeyCode)) {
return ''
}
keyIndex = url.indexOf(`&${key}`, keyIndex + 1)
}
encoded = /[%+]/.test(url)
if (!encoded) {
return undefined
}
// fallback to default routine
if (key) {
const params = multiple ? searchParams.getAll(key) : searchParams.get(key)
return multiple ? (params?.length ? params : undefined) : params ?? undefined
}
const results: Record<string, string> | Record<string, string[]> = {}
encoded ??= /[%+]/.test(url)
const result = Array.from(searchParams.keys()).reduce<
Record<string, string | undefined> | Record<string, string[]>
>((acc, key) => {
acc[key] = multiple ? searchParams.getAll(key) : searchParams.get(key) ?? undefined
return acc
}, {})
let keyIndex = url.indexOf('?', 8)
while (keyIndex !== -1) {
const nextKeyIndex = url.indexOf('&', keyIndex + 1)
let valueIndex = url.indexOf('=', keyIndex)
if (valueIndex > nextKeyIndex && nextKeyIndex !== -1) {
valueIndex = -1
}
let name = url.slice(
keyIndex + 1,
valueIndex === -1 ? (nextKeyIndex === -1 ? undefined : nextKeyIndex) : valueIndex
)
if (encoded) {
name = _decodeURI(name)
}
keyIndex = nextKeyIndex
if (name === '') {
continue
}
let value
if (valueIndex === -1) {
value = ''
} else {
value = url.slice(valueIndex + 1, nextKeyIndex === -1 ? undefined : nextKeyIndex)
if (encoded) {
value = _decodeURI(value)
}
}
if (multiple) {
if (!(results[name] && Array.isArray(results[name]))) {
results[name] = []
}
;(results[name] as string[]).push(value)
} else {
results[name] ??= value
}
}
return key ? results[key] : results
return result
}
export const getQueryParam: (