Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 19 additions & 19 deletions packages/next/src/resource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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, {
Expand All @@ -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') {
Expand Down
8 changes: 4 additions & 4 deletions packages/react/src/core/endpoint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,15 +132,15 @@ export type ApiRouteResponse<TResponses extends Partial<Record<ApiHttpStatus, In

export type ApiRouteHandler<TApiRouteSchema extends ApiRouteSchema = ApiRouteSchema> = (
payload: ApiRouteHandlerPayload<TApiRouteSchema>,
meta: { request: Request; response: Response }
meta: { request: Request; response: Response; rawBody?: string }
) => Promisable<ApiRouteResponse<TApiRouteSchema['responses']>>

export type ApiRouteHandlerInitial<
TContext extends AnyRequestContextable,
TApiRouteSchema extends ApiRouteSchema,
> = (
payload: ApiRouteHandlerPayload<TApiRouteSchema> & { context: TContext },
meta: { request: Request; response: Response }
meta: { request: Request; response: Response; rawBody?: string }
) => Promisable<ApiRouteResponse<TApiRouteSchema['responses']>>

export type GetApiRouteSchemaFromApiRouteHandler<TApiRouteHandler extends ApiRouteHandler<any>> =
Expand Down Expand Up @@ -225,11 +225,11 @@ export function createEndpoint<
): ApiRoute<TApiRouteSchema> {
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<TContext>
const responseBody = await handler(
{ ...payload, context: requestContext },
{ request, response }
{ request, response, rawBody }
)
return responseBody
}),
Expand Down
4 changes: 2 additions & 2 deletions packages/react/src/core/endpoint.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export function withValidator<TApiRouteSchema extends ApiRouteSchema>(
): ApiRouteHandler<TApiRouteSchema> {
const wrappedHandler = async (
payload: ApiRouteHandlerPayload<TApiRouteSchema>,
{ 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) {
Expand All @@ -26,7 +26,7 @@ export function withValidator<TApiRouteSchema extends ApiRouteSchema>(
}

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,
Expand Down
Loading