0
0
mirror of https://github.com/honojs/hono.git synced 2024-12-01 11:51:01 +01:00
hono/deno_dist/utils/body.ts
Sor4chi e4f7f971a8
feat: parseBody() for multi values' field (#1528)
* feat: add "all" option to parseBody

* feat: add parseBody option to `req.parseBody()`

* test: add single value (override) and multiple value cases to praseBody

* test: split parse case of parseBody

* chore: denoify

* refactor(body): make clear parseBody logic

* chore: denoify

* fix: single value of the field should not be parsed to array

* test: add some case of single value's field in "all" option

* chore: denoify
2023-10-05 16:33:56 +09:00

71 lines
1.8 KiB
TypeScript

import type { HonoRequest } from '../request.ts'
export type BodyData = Record<string, string | File | (string | File)[]>
export type ParseBodyOptions = {
/**
* Parse all fields with multiple values should be parsed as an array.
* @default false
* @example
* ```ts
* const data = new FormData()
* data.append('file', 'aaa')
* data.append('file', 'bbb')
* data.append('message', 'hello')
* ```
*
* If `all` is `false`:
* parseBody should return `{ file: 'bbb', message: 'hello' }`
*
* If `all` is `true`:
* parseBody should return `{ file: ['aaa', 'bbb'], message: 'hello' }`
*/
all?: boolean
}
const isArrayField = (value: unknown): value is (string | File)[] => {
return Array.isArray(value)
}
export const parseBody = async <T extends BodyData = BodyData>(
request: HonoRequest | Request,
options: ParseBodyOptions = {
all: false,
}
): Promise<T> => {
let body: BodyData = {}
const contentType = request.headers.get('Content-Type')
if (
contentType &&
(contentType.startsWith('multipart/form-data') ||
contentType.startsWith('application/x-www-form-urlencoded'))
) {
const formData = await request.formData()
if (formData) {
const form: BodyData = {}
formData.forEach((value, key) => {
const shouldParseAllValues = options.all || key.slice(-2) === '[]'
if (!shouldParseAllValues) {
form[key] = value // override if same key
return
}
if (form[key] && isArrayField(form[key])) {
;(form[key] as (string | File)[]).push(value) // append if same key
return
}
if (form[key]) {
form[key] = [form[key] as string | File, value] // convert to array if multiple values
return
}
form[key] = value
})
body = form
}
}
return body as T
}