How to Clean Request Params in NestJS Requests
The NestJS framework is a revelation for anyone who has built apps using vanilla NodeJS with ExpressJS. The module structure, file generators, and class and method decorators make coding more approachable and repeatable. Before, you had to build a lot of functionality by hand, but with NestJS you only have to know what to set up. One feature that can be difficult to set up is request param safety. Let us talk about how to clean request params in NestJS.
Why Would We Want to Validate Params?
What do I mean by cleaning request params? Much of the internet is built around the idea of client-server architecture. A client wants a page or resource and makes a server request. The server looks at the request, determines how to fulfill the request, and responds:
The request can be a simple resource endpoint request. Hitting a “/scores” endpoint could return all game scores for Premier League games. Though this is a realistic endpoint, it is unlikely that a server would want to return all possible games. Sure, the server may control the date range by default. However, more information will likely be provided as params by the user.
These params could be something like a game ID. The route would become “games/12” which may return a game result for Manchester City vs. Arsenal. Or, the user may use query params in their request to return all games for a team for a specific year “/games?team=arsenal&year=2023.”
When the request comes into the server, the server code reads and matches the route to a specific controller endpoint. During this process, the server will separate the params for later use.
This is a simple, but effective way to pass more information from the client to the server. How could this be bad? The server will read everything in the path and the optional body of the request. There is no built-in limit for what can be passed from the client to the server. The client could change our last request to “/games?team=arsenal&year=2023&userAdmin=true.” If there is a setting for session management and a boolean value for the role of the session user, a request like this could give unauthorized permissions to the user.
The server does not control what is sent to it, so it needs to be set up to only accept what is necessary to complete a request. For security and server safety, you must ensure that your controllers validate and clean your params to prevent any bugs from causing issues to your services or customers.
How to Clean Request Params in NestJS
We understand how client-server request-response lifecycles work and why we should clean our params. How do we implement this in NestJS? There are two parts to implementing request param safety: configuration of a ValidationPipe and creating a DTO (data transfer object) for a specific route.
The ValidationPipe is a middleware between the incoming request and the controller logic for handling the request. It is used to validate data coming into the controller for each request. The Validation Pipe can be applied on a per-controller route action, or globally to give coverage to your entire app.
We would like to have global coverage. This saves us from writing repetitive code of binding a ValidationPipe instance to each controller action and prevents us from forgetting validation on any routes.
To globally bind validation we can go to our project’s “main.ts” file and add the following configuration:
When bootstrapping our NestJS app, we will bind a new instance of the ValidationPipe to our app. The example above creates the ValidationPipe, but we need to give it more information on how to validate. To add param cleaning, we want to have the ValidationPipe whitelist the values it is given.
With whitelisting, we create a list of acceptable values for the ValidationPipe. There are two properties we can set on the ValidationPipe to determine how to respond to non-allowed params:
The first option, “whitelist,” will remove or drop any params not specified by a DTO or other params list options. After stripping the non-listed params, it will pass the remaining values to the controller and continue execution.
Our second option, “forbidNonWhitelisted” does not strip out the unlisted params. Instead, once it has found an unlisted param in the request, it will throw an exception and exit execution.
Depending on what level of safety your controller routes and actions need determines which of these two configuration options to use. Now, you should understand the basics for setting up param safety checks in your NestJS application. The next step is getting familiar with DTOs to control the list of accepted parameters for each controller action.