How to format response before sending in Nest.js?

限于喜欢 提交于 2020-06-23 14:52:13

问题


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 };
      }
}

回答1:


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.



来源:https://stackoverflow.com/questions/60189849/how-to-format-response-before-sending-in-nest-js

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!