
Lesson Description
The "Validation Middleware" Lesson is part of the full, API Design in Node.js, v5 course featured in this preview video. Here's what you'd learn in this lesson:
Scott demonstrates using Zod middleware to validate request bodies, handle errors, and enforce input checks before route handlers, improving code clarity and preventing unexpected data issues.
Transcript from the "Validation Middleware" Lesson
[00:00:00]
>> Speaker 1: One of the big things that I always do when I make an API is validate the inputs, OK So before I run my middleware, before I run my handler specifically, I want to protect
[00:00:00]
I don't want to have to be in my handlers doing a bunch of if checks if this exists, if this, if this, like I just want to assume that everything I need for this handler to run has already been validated and given
[00:00:00]
So the best way I can do that is to validate the inputs that are passed to those handlers, so I don't have to write all those if statements And the best way to do that, in my opinion, is to write the right middleware for it, so that's what we'll do—we'll write some middleware to validate some inputs for the handlers and controllers that we'll be writing later
[00:00:00]
So what we can do is create some middleware helper functions that can take in a Zod schema, any Zod schema, and then depending on that function, whether it's validating the body, the parameters, or the query, it'll validate that object against the schema and log the errors, very similar to what we did in the ENV file
[00:00:00]
Let's do that I'm going to go to my source, make a new folder here, call it middleware Make a new file, validation I'm going to import some types from Express—these are all just going to be types, so I can just say import type
[00:00:00]
I want the request, the response, and the next function Then I'll import some things from Zod: the Zod schema and Zod error The first one we're going to do is validate a body, so this is a payload that you send up on a PUT or POST request
[00:00:00]
We want to validate the body So we'll export a constant validate body, which is a middleware that takes in a schema that we want to enforce Because this is a higher-order function—a function that returns a function—we need to return a middleware function
[00:00:00]
Remember, a middleware function is just a function that takes in three arguments: request, response, and next We're going to try to catch this because Zod will throw an error if validation fails, and we don't want that to break our server
[00:00:00]
We have to handle all errors in our server; otherwise, it'll die So try-catch is a great way to do that—it's a start, not going to save you from everything, but it's a start
[00:00:00]
First, let's validate the body We'll say validated data equals the schema parse, passing in request body If that's good to go, we'll add it right back to the body
[00:00:00]
The reason we reassign it back is that maybe this schema has defaults or coercions that modify the body The result of parsing that schema would include those modifications, so we want to attach that to ensure our expectations line up with what actually happened
[00:00:00]
Then we want to call next with no errors—that's the happy path The sad path is when there's an error If it's a Zod error, we return a 400 status with a JSON object explaining where the request went wrong
[00:00:00]
We'll include validation details like the error path and message If it's not a Zod error, we'll call next and pass the error to the error handler To demonstrate how we'll use this, let's look at a habit route
[00:00:00]
We'll import validate body and Zod In the POST route, we'll create a create habit schema using Z.object, specifying the fields we want to validate—in this case, a name that must be a string
[00:00:00]
We can add validate body as middleware right in the route, passing in the create habit schema Now, before the handler runs, it will validate the body If validation fails, it won't call the handler
[00:00:00]
This means we don't need to do manual if checks inside the handler We tested this by sending a POST request without a name, and it correctly returned a validation error explaining that a name is required
[00:00:00]
By using this approach, we get robust input validation for free, just by defining a schema and passing it to the middleware I would never make an API without an input validator
Learn Straight from the Experts Who Shape the Modern Web
- In-depth Courses
- Industry Leading Experts
- Learning Paths
- Live Interactive Workshops