Errors
zhttp
has a built in error handler (opens in a new tab), which will catch any sort of error thrown in an endpoint or middleware.
@zhttp/errors
Any type of unknown error will be logged and will result in a InternalServerError
response (http status code 500).
If you want to throw a specific type of error which will be reflectced in the http response, you can use the @zhttp/errors
library.
// ../../../examples/concepts-errors.ts
import { z } from 'zod'
import { controller, get } from '@zhttp/core'
import { NotFoundError } from '@zhttp/errors'
// Let's presume we're talking to some sort of database
const db: any = undefined
export const vegetablesController = controller('vegetables')
vegetablesController.endpoint(
get('/vegetables/:vegetableId', 'getVegetableDetails')
.input({
params: z.object({
vegetableId: z.string().uuid()
})
})
.response(z.object({
message: z.string()
}))
.handler(async ({ params: { vegetableId } }) => {
const vegetableDetails = await db.getVegetableById(vegetableId)
if (vegetableDetails == null) {
// ✨✨✨✨✨✨✨✨✨
throw new NotFoundError(`Vegetable with id ${vegetableId} does not exist`)
// ⬆ This will result in a 404 response
// ✨✨✨✨✨✨✨✨✨
}
return vegetableDetails
})
)
Validation errors
If an error is detected as part of the request input validation, the server will send a ValidationError
response, including an error message explaining what's wrong.
If an error is detected as part of the request output validation, an InternalServerError
is returned, and error message is logged.
// ../../../examples/validation-errors.ts
import { z } from 'zod'
import { controller, get } from '@zhttp/core'
export const validationExampleController = controller('validationExample')
validationExampleController.endpoint(
get('/hello', 'getGreeting')
.input({
query: z.object({
// If a name shorter than 5 characcters is provided, then the server will responde with a ValidationError.
name: z.string().min(5)
})
})
.response(z.object({
message: z.string()
}))
.handler(async ({ query }) => {
return {
message: `Hello ${query.name ?? 'everyone'}!`
}
})
)
validationExampleController.endpoint(
get('/goodbye', 'getGoodbye')
.input({
query: z.object({
name: z.string().optional()
})
})
.response(z.object({
message: z.string()
}))
.handler(async ({ query }) => {
return {
thisKeyShouldntBeHere: 'noBueno'
} as any
// ⬆ As zhttp is typesafe, you actually have to manually $x&! up the typing
// to provoke an output validation error :)
// This will result in an InternalServerError.
})
)