Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to format response before sending in Nest.js?

I followed the documentation and was able to add an interceptor for response mapping.

I want a consistent json format output for responses.

How can I achieve this with interceptor or with something else better than this approach.

{
  "statusCode": 201,
  "message": "Custom Dynamic Message"
  "data": {
     // properties
     meta: {}
  }
}

transform.interceptor.ts

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

export interface Response<T> {
  statusCode: number;
  data: T;
}

@Injectable()
export class TransformInterceptor<T>
  implements NestInterceptor<T, Response<T>> {
  intercept(
    context: ExecutionContext,
    next: CallHandler,
  ): Observable<Response<T>> {
    return next
      .handle()
      .pipe(
        map((data) => ({
          statusCode: context.switchToHttp().getResponse().statusCode,
          data,
        })),
      );
  }
}

app.controller.ts

export class AppController {
      @Post('login')
      @UseGuards(AuthGuard('local'))
      @ApiOperation({ summary: 'Login user' })
      @ApiBody({ type: LoginDto })
      @ApiOkResponse({ content: { 'application/json': {} } })
      @UseInterceptors(TransformInterceptor)
      async login(@Request() req) {
        const result = await this.authService.login(req.user);
        return { message: 'Thank you!', result };
      }
}
like image 731
Istiyak Tailor Avatar asked Feb 12 '20 13:02

Istiyak Tailor


People also ask

How do I set response headers in NestJS?

To specify a custom response header, you can either use a @Header() decorator or a library-specific response object (and call res. header() directly). Hint Import Header from the @nestjs/common package.

What is DTO in NestJS?

DTO is the short name of Data Transfer Object. DTO is used in order to validate incoming requests. The DTO on its own is more of a guideline for the developer and those who consume the API to know what kind of shape the request body expects to be, it doesn't actually run any validations on its own!!!.

How do I use NestJS query parameters?

To get all query parameter values from a GET request, you can use the @Query() decorator function from the @nestjs/common module inside the parameter brackets of the controller's respective method in Nestjs.

What is interceptor in NestJS?

An interceptor is a class annotated with the @Injectable() decorator and implements the NestInterceptor interface. Interceptors have a set of useful capabilities which are inspired by the Aspect Oriented Programming (AOP) technique. They make it possible to: bind extra logic before / after method execution.


Video Answer


1 Answers

If I am understanding what you are doing with your controller response and your overall interceptor response, what you can do is something similar:

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

export interface Response<T> {
  statusCode: number;
  message: string;
  data: T;
}

@Injectable()
export class TransformInterceptor<T>
  implements NestInterceptor<T, Response<T>> {
  intercept(
    context: ExecutionContext,
    next: CallHandler,
  ): Observable<Response<T>> {
    return next
      .handle()
      .pipe(
        map((data) => ({
          statusCode: context.switchToHttp().getResponse().statusCode,
          message: data.message
          data: {
            result: data.result,
            meta: {} // if this is supposed to be the actual return then replace {} with data.result
          }
        })),
      );
  }
}

And keep your controller return as {message: 'Custom message', result}.

Another option, which would require more upfront but possible allow for cleaner code would be to create a custom decorator that reflected a value (message) from the class and method and then retrieved that value in the interceptor after injecting the reflector, but again, that would take more upfront effort to set up.

like image 169
Jay McDoniel Avatar answered Oct 16 '22 05:10

Jay McDoniel