2023-08-18 09:25:48 +02:00
|
|
|
import type { HonoRequest } from '../request.ts'
|
|
|
|
|
2023-10-05 09:33:56 +02:00
|
|
|
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)
|
|
|
|
}
|
2022-09-20 15:01:03 +02:00
|
|
|
|
2023-08-05 11:10:12 +02:00
|
|
|
export const parseBody = async <T extends BodyData = BodyData>(
|
2023-10-05 09:33:56 +02:00
|
|
|
request: HonoRequest | Request,
|
|
|
|
options: ParseBodyOptions = {
|
|
|
|
all: false,
|
|
|
|
}
|
2023-08-05 11:10:12 +02:00
|
|
|
): Promise<T> => {
|
2023-01-03 00:25:21 +01:00
|
|
|
let body: BodyData = {}
|
2023-09-03 07:43:01 +02:00
|
|
|
const contentType = request.headers.get('Content-Type')
|
|
|
|
|
2022-08-27 04:38:48 +02:00
|
|
|
if (
|
|
|
|
contentType &&
|
|
|
|
(contentType.startsWith('multipart/form-data') ||
|
2023-06-21 15:51:59 +02:00
|
|
|
contentType.startsWith('application/x-www-form-urlencoded'))
|
2022-08-27 04:38:48 +02:00
|
|
|
) {
|
2023-09-03 07:43:01 +02:00
|
|
|
const formData = await request.formData()
|
|
|
|
if (formData) {
|
|
|
|
const form: BodyData = {}
|
|
|
|
formData.forEach((value, key) => {
|
2023-10-05 09:33:56 +02:00
|
|
|
const shouldParseAllValues = options.all || key.slice(-2) === '[]'
|
|
|
|
|
|
|
|
if (!shouldParseAllValues) {
|
|
|
|
form[key] = value // override if same key
|
|
|
|
return
|
2023-09-16 18:09:25 +02:00
|
|
|
}
|
2023-10-05 09:33:56 +02:00
|
|
|
|
|
|
|
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
|
2023-09-03 07:43:01 +02:00
|
|
|
})
|
|
|
|
body = form
|
|
|
|
}
|
2022-07-02 08:09:45 +02:00
|
|
|
}
|
2023-08-05 11:10:12 +02:00
|
|
|
return body as T
|
2022-07-02 08:09:45 +02:00
|
|
|
}
|