Hapi uses the Joi module for validation, but it doesn't ship with Hapi, so I need to require it in separately. Validation can be configured by adding a validate object to the route's config area. Validate looks for three properties, params, payload, and query. Let's start with params.
Joi allows me to describe what I expect the request params object to look like. I expect request.params to be an object, so I'll set the params property to the result of the Joi.object method, and I'll pass in an object that will describe the keys I expect to be in the request.params object.
Since my path only contains one variable, ID, I'm only going to add an ID key, set to Joi.number, because I expect the ID to be a number. Now, I'll make a post request to my route, leaving the ID parameter off, since it's optional, to make sure it works.
I see a 200 response. The response payload contains all of the params, payload data, and query string data that I passed with the request. They're all empty, because I didn't pass in any data. Then I'll make the same request again, adding 123 for the ID.
I still get a 200, and the ID param shows up in the response. If I make another request, this time setting the ID param to Mike, the request fails with a status code of 400, bad request, and an error message telling me exactly why it failed is included in the response payload.
Request payload validation works the same way. First, I'll make a request that includes posting a JSON payload to the server. I'll use ID and 123 again. You can see that the payload now includes ID-colon-123 in the response.
To add validation for the payload, I'll add a payload key to the validate config object. It, too, will be a Joi object with an ID and Joi number pair.
Now that I'm validating the payload, if I make a request that includes a key that is not included in the validation rules, such as email, the server responds with 400, bad request, and tells me that email is not allowed.
This behavior is intentional. To correct it, I can simply add an email key to my payload validation. This time, I'll use Joi.string to validate the email. After adding email to the payload validation, the request succeeds, and email is included in the response payload.
If I wanted to allow email in the payload without having to add it to the payload validation object, I can chain the method unknown to the Joi.object call. The request succeeds, and still includes email in the response, even though I removed the email key from the payload validation config.
The last thing I want to show is that query string params can be validated the same way. I'll change payload to query, and remove the unknown call, then, make a request that includes ID equals 123 in the query string portion of the URL.
The request succeeds, and ID is included in the query portion of the response payload. When I make the request again, changing the value of ID to the string foo, the request fails with a 400.