You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Nest.js部署Cloud Run后遇QueryFailedError:where子句含NaN列

Cloud Run部署Nest.js后IP转十进制查询报错的排查与解决

错误信息

QueryFailedError: Unknown column 'NaN' in 'where clause' at Query.onResult (/node_modules/typeorm/driver/mysql/MysqlQueryRunner.js:158:37) at Query.execute (/node_modules/mysql2/lib/commands/command.js:36:14) at PoolConnection.handlePacket (/node_modules/mysql2/lib/connection.js:478:34) at PacketParser.onPacket (/node_modules/mysql2/lib/connection.js:97:12) at PacketParser.executeStart (/node_modules/mysql2/lib/packet_parser.js:75:16) at Socket. (/node_modules/mysql2/lib/connection.js:104:25) at Socket.emit (node:events:514:28) at addChunk (node:internal/streams/readable:324:12) at readableAddChunk (node:internal/streams/readable:297:9) at Readable.push (node:internal/streams/readable:234:10)

根本原因

本地环境中req.ip能直接拿到客户端真实IPv4地址,转换正常;但Cloud Run作为托管服务,请求会经过Google的反向代理层,默认情况下Nest.js(基于Express/Fastify)不会信任代理,导致req.ip获取到的是容器内部IP(如127.0.0.1或IPv6格式地址),而你的ipToDecimal函数仅支持标准IPv4转换,无法处理这类异常IP,最终返回NaN,代入查询后触发SQL语法错误。

解决步骤

1. 配置Nest.js信任反向代理

在main.ts中添加代理信任配置,让框架识别Cloud Run的代理请求,从而获取真实客户端IP:

// main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  
  // 信任所有代理(Cloud Run环境下安全,因为代理由Google管理)
  app.enableCors(); // 按需配置跨域规则
  app.set('trust proxy', true); // Express底层配置,若使用Fastify需替换为对应代理信任逻辑
  
  await app.listen(process.env.PORT || 3000);
}
bootstrap();

2. 增强IP转换函数的兼容性

修改ipToDecimal函数,增加IP格式校验与异常处理,避免返回NaN:

export function ipToDecimal(ip: string): number | null {
  // 校验是否为合法IPv4地址
  const ipv4Regex = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
  if (!ipv4Regex.test(ip)) {
    // 若为IPv6或无效IP,返回null标记异常
    return null;
  }
  
  // 原有IPv4转十进制逻辑
  const parts = ip.split('.').map(Number);
  return (parts[0] << 24) + (parts[1] << 16) + (parts[2] << 8) + parts[3];
}

3. 服务层增加错误拦截

在getStoreIdByIP中检查转换结果,避免执行无效查询:

async getStoreIdByIP(ip: string): Promise<StoreIdDto | ProblemDto> {
    const ipDecimal = ipToDecimal(ip);
    if (ipDecimal === null || isNaN(ipDecimal)) {
        return { status: 400, message: '无效的客户端IP' };
    }
    const store = await this.findStoreByIpNum(ipDecimal);

    // 剩余业务逻辑...
}

验证方法

  1. 部署修改后的代码到Cloud Run
  2. 在getStoreByIP接口中添加日志,打印req.ip和转换后的ipDecimal值
  3. 发起请求后查看Cloud Run日志,确认req.ip为真实客户端IPv4,且ipDecimal为有效数值

内容的提问来源于stack exchange,提问作者Dariia

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 07:57:04