NestJS GraphQL ThrottlerGuard报错:Cannot read properties of undefined (reading 'ip')
NestJS + GraphQL 限流时"Cannot read properties of undefined (reading 'ip')"问题修复
问题背景
使用NestJS、GraphQL和@nestjs/throttler开发API实现请求限流,自定义了GqlThrottlerGuard适配GraphQL场景,但发起查询时控制台抛出错误:
Cannot read properties of undefined (reading 'ip')
尽管报错,限流功能仍正常工作——连续3次请求后会正确触发"Too Many Requests"响应。已尝试以下操作但问题未解决:
- 验证限流规则有效性
- 按照官方文档实现自定义守卫
- 配置
trust proxy - 多种方式从上下文提取请求对象
- 检查
ctx.req属性是否存在 - 重写
getTracker方法
问题原因
核心原因是ThrottlerGuard的默认逻辑中,部分代码路径未正确适配GraphQL上下文结构。自定义守卫虽已提取req对象用于限流计数,但ThrottlerGuard内部的IP获取逻辑仍在尝试从原始HTTP上下文而非GraphQL上下文中读取请求对象,导致读取ip时出现undefined。
解决方案
方案1:重写getTracker方法直接获取IP
在自定义GqlThrottlerGuard中,同时重写getRequestResponse和getTracker方法,确保IP从GraphQL上下文的请求对象中获取:
import { ExecutionContext, Injectable } from '@nestjs/common'; import { GqlExecutionContext } from '@nestjs/graphql'; import { ThrottlerGuard } from '@nestjs/throttler'; @Injectable() export class GqlThrottlerGuard extends ThrottlerGuard { getRequestResponse(context: ExecutionContext) { const gqlCtx = GqlExecutionContext.create(context); const ctx = gqlCtx.getContext(); return { req: ctx.req, res: ctx.res }; } protected getTracker(context: ExecutionContext): string { const { req } = this.getRequestResponse(context); // 根据部署环境调整IP获取逻辑,比如处理反向代理场景 return req.ip || req.ips[0] || 'unknown'; } }
方案2:确保GraphQL上下文传递完整HTTP对象
检查GraphQL模块配置,确保上下文正确传递req和res:
GraphQLModule.forRoot({ // 其他配置项 context: ({ req, res }) => ({ req, res }), }),
方案3:重写handleRequest跳过父类错误逻辑(临时方案)
若上述方案无效,可重写handleRequest方法,绕过父类中触发错误的IP校验步骤(不推荐长期使用):
import { ThrottlerException } from '@nestjs/throttler'; // ... 其他代码 protected async handleRequest( context: ExecutionContext, limit: number, ttl: number, ): Promise<boolean> { const { req } = this.getRequestResponse(context); const tracker = this.getTracker(context); const key = this.generateKey(req, tracker); const { totalHits } = await this.storageService.increment(key, ttl); if (totalHits > limit) { throw new ThrottlerException(); } return true; }
验证步骤
- 重启NestJS服务
- 发起GraphQL查询,确认控制台不再抛出"Cannot read properties of undefined (reading 'ip')"错误
- 连续发起超过限流阈值的请求,验证"Too Many Requests"响应正常触发
内容的提问来源于stack exchange,提问作者Andres Eduardo Rosas Alpiri
相关产品推荐
相关产品推荐

