NestJS 拦截器 - 将数据附加到传入请求标头或正文

Ami*_*mit 7 javascript node.js nestjs

我正在尝试修改 NestJS 传入请求并将一些数据附加到标头或正文。我能够用我的数据替换所有身体数据,但我想附加而不是删除传入的身体数据。

这是我的代码

export class MyInterceptor implements NestInterceptor {
  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    const request = context.switchToHttp().getRequest();
    
    
    const token = request.headers['authorization'];
    if (token) {
      const decoded = jwt_decode(token);
      request.body['userId'] = decoded['id'];
    }

    return next.handle();
  }
}
Run Code Online (Sandbox Code Playgroud)

提前致谢

Iso*_*ted 7

我添加了两个示例,因为在运行拦截器测试后,它通过了,没有任何问题。当然,我的示例与您的设置有很大不同,但是,希望它能给您足够的见解:

测试文件:


  test('should not mutate entire request body object', () => {
    const dto = {
      username: 'testuser',
      email: 'test@domain.com',
    };

    const headers = {
      authorization: 'Bearer sdkfjdsakfjdkjfdal',
    };

    return request(app.getHttpServer())
      .post('/')
      .send(dto)
      .set(headers)
      .expect(({ body }) => {
        expect(body.userId).toBeDefined();
        delete body.userId;

        expect(body).toStrictEqual(dto);
      });
  });
Run Code Online (Sandbox Code Playgroud)

我理解您的问题是试图获取有关经过身份验证的用户的信息,然后返回/稍后使用它?但是,您当前的实现似乎完全覆盖了request.body而不是将您的属性附加到原始对象。

拦截器:



@Injectable()
export class HttpRequestBodyInterceptor implements NestInterceptor {
  intercept(context: ExecutionContext, next: CallHandler): Observable {
    const request = context.switchToHttp().getRequest();
    const token = request.headers['authorization'];

    if (token) {
      // decode token
      request.body['userId'] = 'user_123456789';
    }

    return next.handle();
  }
}
Run Code Online (Sandbox Code Playgroud)

控制器:


@Controller()
export class AppController {
  constructor(private readonly appService: AppService) {}

  @Post()
  @UseInterceptors(HttpRequestBodyInterceptor)
  getHello(@Req() req): string {
    return req.body;
  }
}
Run Code Online (Sandbox Code Playgroud)

这将返回正确的响应并且测试将通过。但是,您可能会发现更可靠的解决方案是:


@Injectable()
export class HttpRequestBodyInterceptor implements NestInterceptor {
  intercept(context: ExecutionContext, next: CallHandler): Observable {
    const request = context.switchToHttp().getRequest();
    const token = request.headers['authorization'];

    if (token) {
      // decode token
      request.userId = 'user_123456789';
    }

    return next.handle();
  }
}
Run Code Online (Sandbox Code Playgroud)

然后通过以下方式在您的控制器中访问它:


@Controller()
export class AppController {
  constructor(private readonly appService: AppService) {}

  @Post()
  @UseInterceptors(HttpRequestBodyInterceptor)
  getHello(@Req() req) {
    return {
      userId: req.userId,
      ...req.body,
    };
  }
}
Run Code Online (Sandbox Code Playgroud)

最后,如果您对拦截器的唯一需要是获取该userId属性,您可能会发现https://docs.nestjs.com/security/authentication#jwt-functionity很有用。