NestJS: How to Send Custom Headers with Response

Updated: January 1, 2024 By: Guest Contributor Post a comment

Introduction

NestJS, a progressive Node.js framework for building scalable and efficient server-side applications, gives you fine control over your HTTP responses, including the ability to send custom headers. This tutorial will guide you through several methods of adding custom headers to your HTTP responses in NestJS.

Setting Up a Basic NestJS Project

To begin with, let’s set up a simplistic NestJS project for the context of this tutorial. First, ensure you have Node.js installed, then install the Nest CLI:

npm install -g @nestjs/cli
nestjs new custom-headers-project

Navigate to the project directory:

cd custom-headers-project

Install required packages and run your project:

npm install
npm run start

You should now have a default NestJS project running at http://localhost:3000.

Custom Headers in Controllers

A straightforward way to send custom headers is directly within controller methods. Let’s see a simple example:

import { Controller, Get, Res } from '@nestjs/common';
import { Response } from 'express';

@Controller('greet')
export class GreetController {
  @Get()
  sendGreeting(@Res() response: Response) {
    response.set('X-Custom-Header', 'CustomValue');
    response.send('Hello NestJS!');
  }
}

This method leverages the `@Res()` decorator to inject the underlying Express `Response` object, enabling you to add headers as needed.

Using Interceptors for Custom Headers

For more complex scenarios or to apply headers globally, Interceptors are a good choice. Create an Interceptor that manages custom headers:

import { CallHandler, ExecutionContext, Injectable, NestInterceptor } from '@nestjs/common';
import { map } from 'rxjs/operators';

@Injectable()
export class CustomHeadersInterceptor implements NestInterceptor {
  intercept(context: ExecutionContext, next: CallHandler) {
    return next.handle().pipe(
      map(data => {
        const response = context.switchToHttp().getResponse();
        response.setHeader('X-Custom-Header', 'CustomValue');
        return data;
      })
    );
  }
}

You then apply this Interceptor globally in your `main.ts` or target-specific routes using the `@UseInterceptors()` decorator:

// In main.ts for global scope
app.useGlobalInterceptors(new CustomHeadersInterceptor());
// In a controller for specific routes
@UseInterceptors(CustomHeadersInterceptor)
export class SomeController {}

Advanced Header Manipulations

For even finer control, interceptors can be combined with custom decorators or provider services to dynamically generate and apply headers:

import { createParamDecorator, ExecutionContext } from '@nestjs/common';

export const CustomHeader = createParamDecorator(
  (data: unknown, ctx: ExecutionContext) => {
    const response = ctx.switchToHttp().getResponse();
    response.setHeader('Dynamic-Header', someDynamicValueFunction());
  }
);

In this example, `someDynamicValueFunction` would be a service or function you’ve created to determine the exact header value you need to set. Your controller method can now apply this decorator:

@Get()
example(@CustomHeader() customHeader: string) { /* ... */ }

Response Decorators

NestJS provides response decorators like `@Header()` which can be used to set static or dynamic headers directly in route handlers:

import { Controller, Get, Header } from '@nestjs/common';

@Controller('example')
export class ExampleController {
  @Get()
  @Header('X-Static-Header', 'StaticValue')
  staticHeaderExample() {
    return 'Static header set';
  }

  @Get('dynamic')
  dynamicHeaderExample()
  {
    return new Header('X-Dynamic-Header', dynamicValueFunction());
  }
}

NestJS will automatically add these headers to the response sent to the client.

Custom Decorators and Global Filters

You can also create custom decorators combined with global filters to handle headers for error responses. Here’s a simple filter example:

import { ExceptionFilter, Catch, ArgumentsHost, HttpException } from '@nestjs/common';

@Catch(HttpException)
export class CustomHeaderExceptionFilter implements ExceptionFilter {
  catch(exception: HttpException, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse();

    response.header('X-Error-Custom-Header', 'ErrorValue');
    response.status(exception.getStatus()).json(
      exception.getResponse();
    );
  }
}

This custom filter can be used to catch exceptions and add a custom header to the error response.

Conclusion

Throughout this tutorial, we’ve explored several approaches to sending custom headers with responses in NestJS, from simple controller-based methods to global interceptors, decorators, and filters. As you dive into NestJS, you’ll find these techniques foundational for tailoring the HTTP response headers to suit your application’s requirements.