From d3da5af48b057e9331bd496c5f14bfca8e8968f0 Mon Sep 17 00:00:00 2001 From: Desmenez Date: Sun, 12 Oct 2025 23:13:03 +0700 Subject: [PATCH] chore: genseki rawBody --- packages/next/src/resource.ts | 38 +++++++++++------------ packages/react/src/core/endpoint.ts | 8 ++--- packages/react/src/core/endpoint.utils.ts | 4 +-- 3 files changed, 25 insertions(+), 25 deletions(-) diff --git a/packages/next/src/resource.ts b/packages/next/src/resource.ts index aa4083b9..bd33853c 100644 --- a/packages/next/src/resource.ts +++ b/packages/next/src/resource.ts @@ -45,27 +45,27 @@ async function makeApiRoute( const reqHeaders = extractHeaders(req.headers) const reqSearchParams = extractSearchParams(req.nextUrl.searchParams) - // TODO: This logic might not able to handle form data or x-www-form-urlencoded requests correctly - let body: any = {} - try { - if (req.method === 'GET' || req.method === 'HEAD' || req.method === 'OPTIONS') { - body = undefined - } else { - body = await req.json() + let rawBody: string | undefined = undefined + if (!['GET', 'HEAD', 'OPTIONS'].includes(req.method)) { + try { + rawBody = await req.text() + } catch { + rawBody = undefined } - } catch { - // If the request body is not JSON or empty, we will not parse it - // This is useful for file uploads or plain text requests + } - // TODO: Handle plain text and file upload + let body: any = {} + const ct = (req.headers.get('content-type') || '').toLowerCase() + if (rawBody) { + if (!ct.includes('application/json')) { + return Response.json({ message: 'Content-Type must be application/json' }, { status: 400 }) + } - return Response.json( - { message: 'Invalid request body' }, - { - status: 400, - headers: { 'Content-Type': 'application/json' }, - } - ) + try { + body = JSON.parse(rawBody) + } catch { + return Response.json({ message: 'Invalid JSON request body' }, { status: 400 }) + } } const response = new Response(null, { @@ -80,7 +80,7 @@ async function makeApiRoute( query: reqSearchParams, body, }, - { request: req, response } + { request: req, response, rawBody } ) if (response.headers.get('Content-Type') === 'application/json') { diff --git a/packages/react/src/core/endpoint.ts b/packages/react/src/core/endpoint.ts index a00df250..1be5f13e 100644 --- a/packages/react/src/core/endpoint.ts +++ b/packages/react/src/core/endpoint.ts @@ -132,7 +132,7 @@ export type ApiRouteResponse = ( payload: ApiRouteHandlerPayload, - meta: { request: Request; response: Response } + meta: { request: Request; response: Response; rawBody?: string } ) => Promisable> export type ApiRouteHandlerInitial< @@ -140,7 +140,7 @@ export type ApiRouteHandlerInitial< TApiRouteSchema extends ApiRouteSchema, > = ( payload: ApiRouteHandlerPayload & { context: TContext }, - meta: { request: Request; response: Response } + meta: { request: Request; response: Response; rawBody?: string } ) => Promisable> export type GetApiRouteSchemaFromApiRouteHandler> = @@ -225,11 +225,11 @@ export function createEndpoint< ): ApiRoute { return { schema: schema, - handler: withValidator(schema, async (payload, { request, response }) => { + handler: withValidator(schema, async (payload, { request, response, rawBody }) => { const requestContext = context.toRequestContext(request) as ContextToRequestContext const responseBody = await handler( { ...payload, context: requestContext }, - { request, response } + { request, response, rawBody } ) return responseBody }), diff --git a/packages/react/src/core/endpoint.utils.ts b/packages/react/src/core/endpoint.utils.ts index 15acd1de..82765e7b 100644 --- a/packages/react/src/core/endpoint.utils.ts +++ b/packages/react/src/core/endpoint.utils.ts @@ -12,7 +12,7 @@ export function withValidator( ): ApiRouteHandler { const wrappedHandler = async ( payload: ApiRouteHandlerPayload, - { request, response }: { request: Request; response: Response } + { request, response, rawBody }: { request: Request; response: Response; rawBody?: string } ) => { const result = await validateRequestBody(schema, payload) if (result.success === false) { @@ -26,7 +26,7 @@ export function withValidator( } const validatedPayload = result.data - const responseBody = await handler(validatedPayload as any, { request, response }) + const responseBody = await handler(validatedPayload as any, { request, response, rawBody }) const validationError = validateResponseBody( schema,