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

使用njs子请求通过Location头重定向的异常问题排查

问题

需求:在使用app服务前先向其发送请求,当该请求返回状态码302时,将浏览器重定向到该请求响应中的Location地址。

配置文件 nginx.conf

http {
  upstream app {
    server localhost:3000;
  }
  server {
    server_name myhost.local;
    js_import 'lib.js';
    location / {
      js_content lib.check;
    }
    location = /app {
      internal;
      proxy_pass http://app$request_uri;
    }
  }
}

脚本文件 lib.js

async function check(r) {
 let reply = await r.subrequest('/app')
 if (reply.status == 302) {
   r.headersOut['Location'] = reply.headersOut['Location'] // 不生效
   r.headersOut['Foo'] = 'Bar' // 正常生效       
 }
 r.headersOut['Content-Type'] = reply.headersOut['Content-Type'] // 同样正常生效  
 r.return(reply.status, reply.responseText) 
}

问题现象

执行curl -I myhost.local测试,返回的Location头被自动替换为当前请求的Host值,而非预期的目标地址:

curl -I myhost.local 
HTTP/1.1 302 Moved Temporarily
Server: nginx/1.26.2
Location: http://myhost.local/ # Host值
Foo: Bar # 正常
Content-Type: text/html # 正常

已知reply.headersOut中存在正确的Location值,但手动设置r.headersOut['Location']无效,其他响应头正常,如何解决该问题?


解决方案

问题原因

当调用r.return(302, ...)时,Nginx核心模块会自动基于当前请求的Host生成Location头,这个过程会覆盖你之前在r.headersOut中手动设置的Location值,导致自定义地址失效。

修复方法

使用Nginx JavaScript模块提供的r.redirect()方法直接返回重定向响应,该方法会将你传入的地址作为Location头,不会触发Nginx自动生成Location的逻辑。

修改后的lib.js代码:

async function check(r) {
 let reply = await r.subrequest('/app')
 if (reply.status == 302) {
   // 直接用r.redirect返回重定向,传入目标Location和状态码
   return r.redirect(reply.headersOut['Location'], reply.status)
 }
 // 非302状态下正常返回响应
 r.headersOut['Content-Type'] = reply.headersOut['Content-Type']
 r.return(reply.status, reply.responseText) 
}

验证

修改后重新加载Nginx配置,再次执行curl -I myhost.local,即可看到Location头被正确设置为reply.headersOut['Location']中的目标地址。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 19:52:36