import { Controller, Get, Res, HttpStatus } from '@nestjs/common'; import { Response } from 'express'; @Controller('test') export class TestController { @Get() getData(@Res() res: Response) { res.status(HttpStatus.CREATED).set('X-Custom-Header', 'NestJS').json({ message: 'Created' }); } }
The method sets the status code to 201 (Created) using HttpStatus.CREATED. It also sets a custom header 'X-Custom-Header' with value 'NestJS'. The JSON body contains the message.
The Express Response object uses set() to set headers, not header(), setHeader(), or setHeaders(). Also, HttpStatus.NOT_FOUND is valid but header() is not a method.
import { Controller, Get, Res } from '@nestjs/common'; import { Response } from 'express'; @Controller('debug') export class DebugController { @Get() sendHeader(@Res() res: Response) { res.set('X-Debug', 'true'); return { success: true }; } }
When you use @Res() and also return a value, NestJS ignores the manual response methods like res.set(). You must either use res.send() or return the value but not both.
import { Injectable, NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common'; import { Observable, map } from 'rxjs'; @Injectable() export class HeaderInterceptor implements NestInterceptor { intercept(context: ExecutionContext, next: CallHandler): Observable<any> { const response = context.switchToHttp().getResponse(); response.status(202); response.set('X-Intercepted', 'yes'); return next.handle().pipe( map(data => ({ ...data, intercepted: true })) ); } }
The interceptor sets the status code to 202 and adds the header 'X-Intercepted'. It also modifies the response body to include intercepted: true.
When you inject the response object with @Res() and use it to set status or headers, you must send the response manually and not return a value. Returning a value causes NestJS to ignore the manual response calls.