title: NestJS Interceptors: Unable to set HTTP Headers on outgoing requests
body: <p>I am writing APIs in NestJS which have a set of common headers. I decided to use interceptors in order to append headers to outgoing requests. The headers do not get appended to the request and hence the request keeps on failing.</p>
  <p><strong>Interceptor</strong></p>
  <pre><code>import * as utils from '../utils/utils';
  import {
    CallHandler,
    ExecutionContext,
    Injectable,
    NestInterceptor
  } from '@nestjs/common';
  import { HEADERS } from '../middlewares/headers.constant';
  import { Observable } from 'rxjs';
  import { Request } from 'express';
  import { DATA_PARTITION_ID } from '../app.constants';
  
  @Injectable()
  export class HeadersInterceptor implements NestInterceptor {
    intercept(context: ExecutionContext, next: CallHandler): Observable&lt;void&gt; {
      const ctx = context.switchToHttp();
      const request: Request = ctx.getRequest();
  
      this.setHeaders(request);
  
      return next.handle();
    }
  
    private setHeaders(request): void {
      this.updateHeaders(request, HEADERS.ACCEPT, 'application/json');
      this.updateHeaders(request, HEADERS.CONTENT_TYPE, 'application/json');
      this.updateHeaders(request, HEADERS.ACCEPT_ENCODING, 'gzip, deflate, br');
      this.updateHeaders(
        request,
        HEADERS.DATA_PARTITION_ID,
        DATA_PARTITION_ID
      );
      this.updateHeaders(
        request,
        HEADERS.AUTHORIZATION,
        `Bearer ${utils.parseCookies(request).stoken}`
      );
      this.updateHeaders(request, HEADERS.APP_KEY, '');
    }
  
    private updateHeaders(
      request: Request,
      property: string,
      value: string
    ): void {
      if (!request.headers.hasOwnProperty(property)) {
        request.headers[property] = value;
      } else {
        void 0;
      }
    }
  }
  </code></pre>
  <p>This interceptor simply does one thing: Access the request and append the headers and pass the control to next handler.</p>
  <p><strong>Enums</strong></p>
  <pre><code>export enum HEADERS {
    DATA_PARTITION_ID = 'Data-Partition-Id',
    AUTHORIZATION = 'Authorization',
    CONTENT_TYPE = 'Content-Type',
    APP_KEY = 'appkey',
    ACCEPT = 'accept',
    ACCEPT_ENCODING = 'accept-encoding'
  }
  </code></pre>
  <p><strong>Controller</strong></p>
  <pre><code>import { Body, Controller, Post, Req, UseInterceptors } from '@nestjs/common';
  import { HeadersInterceptor } from '../interceptors/headers.interceptor';
  import { SearchData } from './models/search-data.model';
  import { SearchResults } from './models/search-results.model';
  import { SearchService } from './search.service';
  
  @Controller('')
  @UseInterceptors(new HeadersInterceptor())
  export class SearchController {
    constructor(private searchService: SearchService) {}
  
    @Post('api/search')
    async searchDataById(@Body() searchData: SearchData, @Req() req): Promise&lt;SearchResults&gt; {
      console.log(req.headers);
      return await this.searchService.getSearchResultsById(searchData);
    }
  }
  </code></pre>
  <p><strong>Service</strong></p>
  <pre><code>import { HttpService, HttpStatus, Injectable } from '@nestjs/common';
  import { AppConfigService } from '../app-config/app-config.service';
  import { DataMappingPayload } from './models/data-mapping-payload.model';
  import { SearchData } from './models/search-data.model';
  import { SearchModelMapper } from './search.service.modelmapper';
  import { SearchResults } from './models/search-results.model';
  import { ServiceException } from '../exception/service.exception';
  
  @Injectable()
  export class SearchService {
    constructor(
      private searchModelMapper: SearchModelMapper,
      private configService: AppConfigService,
      private readonly httpService: HttpService
    ) {}
  
    async getSearchResultsById(searchData: SearchData): Promise&lt;SearchResults&gt; {
      if (searchData.filters.collectionId) {
        console.log(this.configService.appConfig.urls.SEARCH_RESULTS_BY_COLLECTION_ID_URL.replace(
            '${collectionId}',
            searchData.filters.collectionId
          )
        );
        const searchResultsAPI = await this.httpService
          .get(
            this.configService.appConfig.urls.SEARCH_RESULTS_BY_COLLECTION_ID_URL.replace(
              '${collectionId}',
              searchData.filters.collectionId
            )
          )
          .toPromise();
        const kinds = this.searchModelMapper.getUniqueKinds(
          searchResultsAPI.data.results
        );
        const mappingPayload = await this.getDataMapping(kinds);
        return this.searchModelMapper.generateSearchResults(
          kinds,
          mappingPayload,
          searchResultsAPI.data.results
        );
      } else {
        this.raiseException();
      }
    }
  
    async getDataMapping(kinds: string[]): Promise&lt;[]&gt; {
      const entityKindNames: DataMappingPayload = {
        entityKindNames: kinds
      };
      const dataMappingAPI = await this.httpService
        .post(
          this.configService.appConfig.urls.DATA_CATALOG_SERVICE_URL,
          JSON.stringify(entityKindNames)
        )
        .toPromise();
  
      return dataMappingAPI.data.entityViewData;
    }
  
    // To be moved to util functions
    private raiseException(): void {
      throw new ServiceException(
        {
          message: 'This does not have a collection id',
          missing: 'Collection Id',
          code: HttpStatus.BAD_REQUEST
        },
        HttpStatus.BAD_REQUEST
      );
    }
  }
  </code></pre>
  <p>When I access <code>req.headers</code> in the <strong>controller</strong>, I do get all the headers that I needed to set via interceptors.</p>
  <pre><code>{
  [0]   'accept-encoding': 'gzip, deflate, br',
  [0]   'accept-language': 'en-US,en;q=0.9',
  [0]   cookie: '',
  [0]   'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36',
  [0]   'content-type': 'application/json',
  [0]   accept: 'application/json',
  [0]   appkey: '',
  [0]   'cache-control': 'no-cache',
  [0]   'postman-token': 'cb397012-71aa-460a-b66b-28600538faf9',
  [0]   host: 'localhost:8080',
  [0]   'content-length': '77',
  [0]   connection: 'keep-alive',
  [0]   'Data-Partition-Id': 'tenant1',
  [0]   Authorization: 'Bearer TOKEN_HERE'
  [0] }
  </code></pre>
  <p>When I check the logs of the actual request, it says <strong>Authorization</strong> is <code>null</code>. Which means the request is not intercepted and not being appended with headers.</p>
  <p>Has anyone faced similar issue?</p>