[英]Why does nestjs interceptor return undefined?
我正在嘗試在nestjs中實現日志記錄攔截器,以便它捕獲所有請求和響應並將其記錄下來。
因此,我實現了這樣的LoggingInterceptor
import { logger } from './../utils/logger';
import { ExecutionContext, Injectable, NestInterceptor } from '@nestjs/common';
import { Observable, BehaviorSubject, from } from 'rxjs';
import { map, tap, refCount, publish, publishLast } from 'rxjs/operators';
@Injectable()
export class LoggingInterceptorInterceptor implements NestInterceptor {
intercept(context: ExecutionContext, call$: Observable<any>): Observable<any> {
const reqHeaders = context.switchToHttp().getRequest().headers;
const reqBody = context.switchToHttp().getRequest().body;
logger.info('Logging the incoming request:',reqHeaders);
logger.info('Logging the incoming req body:', reqBody);
const now = Date.now();
logger.info('Time of request call is', now);
const serviceBehaviorSubj = new BehaviorSubject<any>(null);
// response will be available only in the call$ observable stream
// so use tap to get a clone of the observable and print the data sent
// this pipe call transforms the response object to start with something called data
// so a default response like "Done", "test" looks now as a json string
// {data : Done} {data: test}
// const anotherrespObs: Observable<any> = call$.pipe(publishLast(), refCount());
// anotherrespObs.pipe(publishLast(), refCount()).subscribe(data => {
// logger.info('Logging the outgoing response', data);
// });
return call$.pipe(map(data => {
console.log('data here is', data);
return ({ dottted: data });
}));
//oo.then(return new Pro)
// return call$.pipe(tap(() => {
// logger.info(`Time of completion is ${Date.now() -now}`);
// }), map(data => {
// console.log('ccccccc', data);
// return data;
// }));
}
}
我知道call $運算符的行為類似於Observable,並且將由nestjs在內部進行訂閱,以將響應發送給客戶端,但是我想在發送之前記錄信息,並可能轉換響應
因此,我使用了rxjs的map()運算符。 如果響應集的類型不是'application / json',則此功能正常運行。 如果Content-Type是'plain / text',則映射操作將被應用並轉換為所需的json對象,然后發送給客戶端,但如果響應已經是application / json類型(即json),則不會賓語。 我無法應用轉換對象。 在記錄發送到map()的值時,我看到它被記錄為json對象的undefined。 那么我如何獲取響應(即使它是一個json對象),也可能記錄下來並進行轉換,然后再將其發送到攔截器中的客戶端
注意:我很警惕響應可能包含敏感信息,但是我可能會使用日志屏蔽來僅屏蔽響應數據,但這目前用於測試目的
這是我能夠在攔截器中記錄響應的示例控制器
@ApiOperation({ title: 'Get - With Params', description: 'Test Method with parms' })
@Get('/getTest/:id1/:id2')
@ApiOkResponse({ description: 'Sample string is emitted' })
@ApiResponse({ status: 404, description: 'The endpoint is unavailable' })
@ApiResponse({ status: 503, description: 'The endpoint cannot be processed' })
// @Header('sampleHeaderKey', 'sampleHeaderValue')
// NOte if you send params in the URL and do not use @param then the URL will
// result in NO such end point
public getConfigDataInResponse(@Param('id1') id1: number, @Param('id2') id2: number, @Req() req) {
logger.info('request headers', req.headers);
logger.info('reqiest params', req.params);
logger.info('reqiest query params', req.query);
logger.info('reqiest body ', req.body);
return 'TEST';
}
這是無法記錄響應的方法,在攔截器中為“未定義”
public getConfigDataInResponse(@Param('id1') id1: number, @Param('id2') id2: number, @Req() req, @Res() res) {
logger.info('request headers', req.headers);
logger.info('reqiest params', req.params);
logger.info('reqiest query params', req.query);
logger.info('reqiest body ', req.body);
res.set('SampeHeader', 'saomevaluie');
res.status(HttpStatus.OK).send('some data');
}
當在控制器方法中注入@Res()
時,使嵌套如此出色的許多功能(如攔截器)將無法使用。
在大多數情況下,不需要注入@Res()
因為可以使用專用裝飾器。 在您的示例中將是:
// Sets the http response code (default for POST is 201, for anything else 200)
@HttpCode(204)
// Sets a custom header
@Header('SampleHeader', 'somevalue')
@Get('/getTest/:id1/:id2')
public getConfigDataInResponse(@Param('id1') id1: number, @Param('id2') id2: number) {
return 'some data';
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.