|
- import { IncomingMessage } from 'http';
- import { getFormValues } from '@theoryofnekomata/formxtra';
- import {
- ENCTYPE_APPLICATION_JSON, ENCTYPE_APPLICATION_OCTET_STREAM,
- ENCTYPE_MULTIPART_FORM_DATA,
- ENCTYPE_X_WWW_FORM_URLENCODED,
- } from '../common';
- import { getBody, parseMultipartFormData } from './request';
-
- export type EncTypeSerializer = (data: unknown) => string;
-
- export type EncTypeSerializerMap = Record<string, EncTypeSerializer>;
-
- export type SerializerOptions = Parameters<typeof getFormValues>[1];
-
- export interface SerializeBodyParams {
- form: HTMLFormElement,
- encType: string,
- serializers?: EncTypeSerializerMap,
- options?: SerializerOptions,
- }
-
- export const DEFAULT_ENCTYPE_SERIALIZERS: EncTypeSerializerMap = {
- [ENCTYPE_APPLICATION_JSON]: (data: unknown) => JSON.stringify(data),
- };
-
- export const serializeBody = (params: SerializeBodyParams) => {
- const {
- form,
- encType,
- serializers = DEFAULT_ENCTYPE_SERIALIZERS,
- options,
- } = params;
-
- if (encType === ENCTYPE_X_WWW_FORM_URLENCODED) {
- return new URLSearchParams(form);
- }
-
- if (encType === ENCTYPE_MULTIPART_FORM_DATA) {
- // type error when provided a submitter element for some reason...
- const FormDataUnknown = FormData as unknown as {
- new(formElement?: HTMLElement, submitter?: HTMLElement): BodyInit;
- };
- return new FormDataUnknown(form, options?.submitter);
- }
-
- if (typeof serializers[encType] === 'function') {
- return serializers[encType](getFormValues(form, options));
- }
-
- throw new Error(`Unsupported encType: ${encType}`);
- };
-
- export type EncTypeDeserializer = (data: string) => unknown;
-
- export type EncTypeDeserializerMap = Record<string, EncTypeDeserializer>;
-
- export interface DeserializeBodyParams {
- req: IncomingMessage,
- deserializers?: EncTypeDeserializerMap,
- }
-
- export const DEFAULT_ENCTYPE_DESERIALIZERS: EncTypeDeserializerMap = {
- [ENCTYPE_APPLICATION_JSON]: (data: string) => JSON.parse(data) as Record<string, unknown>,
- };
-
- export const deserializeBody = async (params: DeserializeBodyParams) => {
- const { req, deserializers = DEFAULT_ENCTYPE_DESERIALIZERS } = params;
- const contentType = req.headers['content-type'] ?? ENCTYPE_APPLICATION_OCTET_STREAM;
-
- if (contentType?.startsWith(`${ENCTYPE_MULTIPART_FORM_DATA};`)) {
- return parseMultipartFormData(req);
- }
-
- const encoding = (req.headers['content-encoding'] ?? 'utf-8') as BufferEncoding;
- const bodyRaw = await getBody(req);
-
- if (contentType === ENCTYPE_X_WWW_FORM_URLENCODED) {
- return Object.fromEntries(
- new URLSearchParams(bodyRaw.toString(encoding)).entries(),
- );
- }
-
- if (typeof deserializers[contentType] === 'function') {
- return deserializers[contentType](bodyRaw.toString(encoding));
- }
-
- return bodyRaw.toString('binary');
- };
|