返回 AiToEarn
response.interceptor.ts
根目录 / project / aitoearn-backend / libs / common / src / interceptors / response.interceptor.ts
1 import type { Request, Response } from 'express'
2 import type { CommonResponse } from '../interfaces'
3 import {
4 CallHandler,
5 ExecutionContext,
6 Logger,
7 NestInterceptor,
8 SetMetadata,
9 StreamableFile,
10 } from '@nestjs/common'
11 import { RENDER_METADATA, SSE_METADATA } from '@nestjs/common/constants'
12 import { map } from 'rxjs'
13 import { ResponseCode } from '../enums'
14 import { getCurrentRequestId, getRequestIdFromHeaders } from './propagation.interceptor'
15
16 const SKIP_RESPONSE_INTERCEPTOR_KEY = Symbol('SkipResponseInterceptor')
17
18 export function SkipResponseInterceptor() {
19 return SetMetadata(SKIP_RESPONSE_INTERCEPTOR_KEY, true)
20 }
21
22 export class ResponseInterceptor implements NestInterceptor {
23 private readonly logger = new Logger(ResponseInterceptor.name)
24 intercept(context: ExecutionContext, next: CallHandler) {
25 const type = context.getType()
26
27 const isRender = Reflect.hasMetadata(RENDER_METADATA, context.getHandler())
28 const isSSE = Reflect.getMetadata(SSE_METADATA, context.getHandler())
29 const skipInterceptor = Reflect.getMetadata(SKIP_RESPONSE_INTERCEPTOR_KEY, context.getHandler())
30
31 if (type === 'http') {
32 const req = context.switchToHttp().getRequest<Request>()
33 const res = context.switchToHttp().getResponse<Response>()
34 const requestId = getRequestIdFromHeaders(req.headers)
35
36 if (!isSSE) {
37 res.header('x-request-id', req.headers['x-request-id'])
38 }
39
40 res.status(200)
41
42 return next.handle().pipe(
43 map((data) => {
44 if (data instanceof StreamableFile || isRender || skipInterceptor) {
45 return data
46 }
47
48 return {
49 data,
50 code: ResponseCode.Success,
51 message: '请求成功',
52 ...(requestId ? { requestId } : {}),
53 }
54 }),
55 )
56 }
57 else if (type === 'rpc') {
58 const startAt = Date.now()
59
60 const ctx = context.switchToRpc()
61 const req = ctx.getContext<{ args: string[] }>()
62 const url = req.args[0] || ''
63 const rpcData = ctx.getData()
64 this.logger.debug(rpcData, `-- ${startAt}-- [${url}] rpcData ----: `)
65
66 return next.handle().pipe(
67 map((data: unknown): CommonResponse<unknown> => {
68 const reqTime = Date.now() - startAt
69 if (reqTime >= 50) {
70 this.logger.verbose(`${url}::${reqTime}ms`)
71 }
72 const requestId = getCurrentRequestId()
73
74 return {
75 data,
76 code: ResponseCode.Success,
77 message: '请求成功',
78 ...(requestId ? { requestId } : {}),
79 }
80 }),
81 )
82 }
83 else {
84 return next.handle()
85 }
86 }
87 }
88
88 lines TYPESCRIPT