NestJS API Development Guide 09: Request and Response - @Req, @Res, @Headers and @Ip Decorators
Video
Watch the full video on YouTube:
Introduction
In this ninth installment of the NestJS guide, we’ll explore how to access request information and control the response in our controllers. NestJS provides a set of decorators that facilitate interaction with these objects, allowing us to obtain headers, cookies, IP addresses, and much more.
@Req Decorator - Accessing the Request
The @Req (or @Request) decorator allows us to access the complete request object, which contains all the information the client sends to our API.
Importing @Req
import { Req } from '@nestjs/common'
import { type Request } from 'express'
Using @Req in a Controller
@Post('example')
example(@Req() req: Request) {
console.log(req.body)
console.log(req.method)
console.log(req.headers)
console.log(req.query)
console.log(req.params)
return 1
}
Information Available in the Request
The request object contains:
- body: The request body
- method: The HTTP method used (GET, POST, PUT, etc.)
- headers: The headers sent by the client
- query: Query string parameters
- params: Route parameters
- cookies: Cookies sent by the client
- IP: The client’s IP address
Example with Headers and Query
@Post('example')
example(@Req() req: Request) {
console.log('Body:', req.body)
console.log('Method:', req.method)
console.log('Headers:', req.headers)
console.log('Query:', req.query)
return 1
}
Important: When using
@Req, NestJS doesn’t automatically execute the validation pipeline. To validate data, it’s preferable to use specific decorators like@Body,@Query, or@Param.
@Ip Decorator - Getting the IP Address
The @Ip decorator allows us to directly obtain the client’s IP address making the request.
Importing @Ip
import { Ip } from '@nestjs/common'
Using @Ip
@Post('example')
example(@Ip() ip: string) {
console.log('IP:', ip)
return 1
}
The returned IP address is a mask representing the client’s approximate location.
@Headers Decorator - Accessing Headers
The @Headers decorator allows us to access the HTTP headers sent by the client.
Importing @Headers
import { Headers } from '@nestjs/common'
Get All Headers
@Post('example')
example(@Headers() headers: Record<string, string>) {
console.log('Headers:', headers)
return 1
}
Get a Specific Header
@Post('example')
example(@Headers('host') host?: string) {
console.log('Host:', host)
return 1
}
When we pass a header name, the decorator returns string | undefined since the header might not be present. If we don’t pass a name, it returns an object with all headers.
@Res Decorator and the Response Object
The @Res (or @Response) decorator gives us access to Express’s response object, allowing us to fully control the response we send to the client.
Importing @Res
import { Res } from '@nestjs/common'
import { type Response } from 'express'
Using @Res to Send Headers
@Post('example')
example(@Res() res: Response) {
res.setHeader('X-Custom-Header', 'my-value')
return res.send(1)
}
Important: When using
@Res()without arguments, you delegate response control to Express (or Fastify). This means NestJS will no longer process the response through its interceptors and pipelines. You must handle sending the response manually using Express methods likeres.send(),res.json(), etc.
Setting Status Code
@Post('example')
example(@Res() res: Response) {
res.status(500)
return res.send('Internal error')
}
passthrough - Delegating the Response to NestJS
When we use @Res, we delegate response control to Express. If we want NestJS to continue managing the lifecycle, we can use the passthrough option:
@Post('example')
example(@Res({ passthrough: true }) res: Response) {
res.setHeader('X-Custom-Header', 'my-value')
return 1 // NestJS will process the response
}
With passthrough: true, we can set headers and status codes while NestJS handles sending the final response through its interceptors and pipelines.
@Header Decorator - Static Headers
The @Header decorator allows us to set response headers statically in the method decorator:
@Post('example')
@Header('X-Custom-Header-2', 'milo')
example() {
return 1
}
This approach is useful for headers that don’t depend on business logic.
@HttpCode Decorator - Custom Status Codes
The @HttpCode decorator allows us to set the HTTP status code that will be sent in the response:
import { HttpCode } from '@nestjs/common'
@Post('example')
@HttpCode(400)
example() {
return 1
}
We can also use the HttpStatus enum from @nestjs/common:
import { HttpCode, HttpStatus } from '@nestjs/common'
@Post('example')
@HttpCode(HttpStatus.BAD_REQUEST)
example() {
return 1
}
Decorators Summary
| Decorator | Function | Example |
|---|---|---|
@Req |
Access complete request | @Req() req: Request |
@Res |
Access complete response | @Res() res: Response |
@Ip |
Get client’s IP | @Ip() ip: string |
@Headers |
Access HTTP headers | @Headers() headers: Record<string, string> |
@Header |
Set static header | @Header('key', 'value') |
@HttpCode |
Set status code | @HttpCode(200) |
Best Practices
- Use specific decorators (
@Body,@Query,@Param) instead of@Reqfor automatic validation - Prefer
@Res({ passthrough: true })when you need to set headers but want NestJS to handle the response - Don’t mix
@Reswithreturnwithoutpassthrough, as Express will take control and NestJS won’t process the response - Use
@HttpCodefor endpoints that need non-standard status codes - Extract business logic from controllers to services or handlers
Conclusion
Request and response decorators in NestJS give us full control over client interaction. From obtaining basic information like IP and headers, to fully controlling the response with custom status codes and headers. Proper use of these decorators is fundamental for creating robust and well-structured APIs.
Repository
💻 Repository: https://github.com/radagva/guia-de-nestjs-example
