taxonomy/content/blog/validation-middleware.mdx

93 lines
2.3 KiB
Text

---
title: Next.js API Routes validation using Middlewares and Yup
date: "2023-01-08"
---
## Middlewares
### withMethods
Let's start with a simple middleware to validate `request.method`.
```ts
import type { NextApiHandler, NextApiRequest, NextApiResponse } from "next"
export function withMethods(methods: string[], handler: NextApiHandler) {
return async function (request: NextApiRequest, response: NextApiResponse) {
if (!methods.includes(request.method)) {
return response.status(405).json("")
}
return handler(request, response)
}
}
```
To use this middleware, we call our API handler by wrapping it inside `withMethods`:
```ts
async function handler(request: NextApiRequest, response: NextApiResponse) {}
export default withMethods(["POST"], handler)
```
### withValidation
Next, we're going to create a middleware to validate `request.body`
```ts
import type { NextApiHandler, NextApiRequest, NextApiResponse } from "next"
import type { ObjectShape, OptionalObjectSchema } from "yup/lib/object"
export function withValidation<T extends OptionalObjectSchema<ObjectShape>>(
schema: T,
handler: NextApiHandler
) {
return async function (request: NextApiRequest, response: NextApiResponse) {
try {
request.body = await schema.validate(request.body)
return handler(request, response)
} catch (error) {
if (error instanceof yup.ValidationError) {
return response.status(422).json(error.message)
}
return response.status(422).json("")
}
}
}
```
This middleware accepts a schema to validate `request.body` against. We use it as follows:
```ts
const postSchema = yup.object({
title: yup.string().required("`Title` field missing."),
body: yup.string().required("`Body` field missing"),
})
interface Post extends yup.TypeOf<typeof postSchema> {}
async function handler(request: NextApiRequest, response: NextApiResponse) {
const post: Post = request.body
// TODO: Save post.
response.status(201).json("")
}
export default withValidation(postSchema, handler)
```
## Chaining
We can call mutiple middlewares by chaining:
```ts title="pages/api/posts"
export default withMethods(["POST"], withValidation(postSchema, handler))
```
## Code
You can check out the code here: [https://github.com/arshad/nextjs-middleware-validation](https://github.com/arshad/nextjs-middleware-validation).