jeecg OpenAPI 模块服务器自调用返回 Null 问题复盘

8 阅读2分钟

1. 问题背景

在开发 OpenAPI 接口转发功能时,本地开发环境(Localhost)调用一切正常。但将代码部署到测试环境(Linux 服务器)后,发现 OpenAPI 转发调用自身接口时,请求未报错,但返回的响应结果为 null

1.1 场景描述

  • 功能:通过 /openapi/call/{path} 接口,根据数据库配置的 API 信息,转发请求到目标服务。
  • 配置:数据库中配置的 origin_url/xxxx(相对路径)。
  • 现象
    • 本地环境:调用成功,返回预期数据。
    • 测试环境:调用成功(HTTP 200),但 restTemplate.exchange(...).getBody() 返回 null

2. 排查过程

2.1 日志分析

通过对比本地和测试环境的日志,发现关键差异:

测试环境日志

INFO  RestUtil.getBaseUrl: http://yuming/context-path
INFO  >>> [OpenAPI Call] 转发最终目标 URL: [http://yuming/context-path/xxxx]
INFO  <<< [OpenAPI Call] 转发调用成功, 响应状态: null

本地环境日志

INFO  RestUtil.getBaseUrl: http://localhost:7001/context-path
INFO  >>> [OpenAPI Call] 转发最终目标 URL: [http://localhost:8080/context-path/xxxx]
INFO  <<< [OpenAPI Call] 转发调用成功, 响应状态: true

2.2 疑点分析

  1. URL 差异
    • 测试环境使用了公网域名
    • 本地环境使用了 localhost
  2. 响应状态
    • 测试环境日志显示 "响应状态: null",说明 RestTemplate 没有抛出异常(如 401/404/500),而是接收到了一个空 Body 的 200 OK 响应。

3. 原因定位

经过分析,问题根源在于 NAT 回流 (NAT Loopback)网关拦截

  1. 请求回环:服务器尝试通过公网域名访问自己。请求路径为: 服务器 -> 公网 DNS -> 网关/防火墙 (Nginx/WAF) -> 服务器
  2. 网关拦截/异常
    • 外部网关可能配置了特定的安全策略,拦截了来自内部 IP 的“公网”请求。
    • 或者网关在转发过程中丢失了某些关键 Header(如 Host),导致后端服务无法正确路由。
    • 某些 WAF 或 Nginx 配置在拦截请求时,可能会返回一个 Content-Length 为 0 的 200 OK 响应,导致 Java 端的 RestTemplate 认为请求成功但没有内容。

4. 解决方案

4.1 解决思路

强制内部调用:当检测到 API 配置为相对路径(即调用本项目自身接口)时,不再通过 RestUtil.getBaseUrl() 获取公网域名,而是直接构造 127.0.0.1 的本地回环地址。

5. 总结

此次修复通过动态获取本地端口和上下文路径,实现了通用的本地回环调用方案。