How to access headers in the nestjs pipe?

Viewed 5451

I'm writing a validation pipe and it needs to get certain infornmation from the token, so I have to somehow pass headers to the validation pipe.

4 Answers

If you need to access a header in a pipe, while the standard @Headers() decorator is not compatible with a pipe, you can create a custom decorator to get the headers that is compatible, as custom decorators always work with pipes.

export const CustomHeaders = createParamDecorator((data: unknown, ctx: ExecutionContext) => {
  const req = ctx.switchToHttp().getRequest();
  return data ? req.headers[data] : req.headers;
})

And now your pipe will work on @CustomHeaders()

To access the request object and its attributes in my CustomPipe, I first create a custom decorator:

request.decorator.ts

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

export const ReqDec = createParamDecorator(
    (data: unknown, ctx: ExecutionContext) => {
        const request = ctx.switchToHttp().getRequest();
        return request;
    }
)

Then I use my decorator in my controller to decorate my CustomPipe:

mycontroller.ts

import { ReqDec } from '../../decorators/request.decorator';

@Get()
async get(@ReqDec(new CustomPipe()) request): Promise<any> 
{...}

Finally I can access the request object in my CustomPipe like this:

custom.pipe.ts

import { Injectable, PipeTransform } from '@nestjs/common';

@Injectable()
export class CustomPipe implements PipeTransform {
  constructor() { }

  transform(request: any) {
    // you can use request, request.query, request.params, request.headers, ...
    return request;
  }
}

It seems that you can't access Request instance in PipeTransform. Use Guards if you need access to Request instance.

  canActivate(
    context: ExecutionContext,
  ): boolean | Promise<boolean> | Observable<boolean> {
    const request = context.switchToHttp().getRequest();
    return validateRequest(request);
  }

Custom decorator approach is by far the simplest and most straight forward but what was forgotten to mention is that in order for it to work the validation pipe has to be initialised with a parameter to allow such behaviour. This is an example for a global validation pipe:

  app.useGlobalPipes(new ValidationPipe({ validateCustomDecorators: true }))
Related