diff --git a/src/common-helpers.ts b/src/common-helpers.ts index 0600d5f..a631014 100644 --- a/src/common-helpers.ts +++ b/src/common-helpers.ts @@ -105,9 +105,6 @@ export function getStatusCodeFromError(error: Error): number { if (error instanceof HttpError) { return error.statusCode; } - if (error instanceof z.ZodError) { - return 400; - } return 500; } diff --git a/src/endpoint.ts b/src/endpoint.ts index 0023fdd..c708fc1 100644 --- a/src/endpoint.ts +++ b/src/endpoint.ts @@ -1,6 +1,7 @@ import { Request, Response } from "express"; import { Logger } from "winston"; import { z } from "zod"; +import { createError } from "http-errors"; import { ApiResponse } from "./api-response"; import { CommonConfig } from "./config-type"; import { @@ -243,7 +244,7 @@ export class Endpoint< logger, }: { method: Method | AuxMethod; - input: Readonly; // Issue #673: input is immutable, since this.inputSchema is combined with ones of middlewares + input: IN; // Issue #673: input is immutable, since this.inputSchema is combined with ones of middlewares request: Request; response: Response; logger: Logger; @@ -257,7 +258,7 @@ export class Endpoint< Object.assign( options, await def.middleware({ - input: await def.input.parseAsync(input), + input, options, request, response, @@ -281,13 +282,13 @@ export class Endpoint< options, logger, }: { - input: Readonly; + input: IN; options: any; logger: Logger; }) { return this.handler({ // final input types transformations for handler - input: (await this.inputSchema.parseAsync(input)) as z.output, + input: input as z.output, options, logger, }); @@ -355,27 +356,37 @@ export class Endpoint< } } const input = getInput(request, config.inputSources); + let parsedInput: IN | null = null; try { - const { options, isStreamClosed } = await this.#runMiddlewares({ - method, - input, - request, - response, - logger, - }); - if (isStreamClosed) { - return; - } - if (method === "options") { - response.status(200).end(); - return; - } - output = await this.#parseOutput( - await this.#parseAndRunHandler({ input, options, logger }) - ); + parsedInput = await this.inputSchema.parseAsync(input); } catch (e) { - error = makeErrorFromAnything(e); + error = createError(400, makeErrorFromAnything(e)); } + + if (parsedInput) { + try { + const { options, isStreamClosed } = await this.#runMiddlewares({ + method, + input: parsedInput, + request, + response, + logger, + }); + if (isStreamClosed) { + return; + } + if (method === "options") { + response.status(200).end(); + return; + } + output = await this.#parseOutput( + await this.#parseAndRunHandler({ input: parsedInput, options, logger }) + ); + } catch (e) { + error = makeErrorFromAnything(e); + } + } + await this.#handleResult({ input, output,