有个需求,访问 www.example.com/api/?ver=c
(参数不区分大小写)时需要跳转到 www.test.test/abc?test=123&config=%2fapi-test
,同时地址栏还要保持不变,并且跳转的域名还含有参数,只能产生一次访问请求,也就是http状态码只能为200,不能触发重定向,需要对客户端完全透明无感知。
经过测试,发现需要做2个步骤,仅仅用rewrite只能实现站内域名的路径重写(服务器内部重写),而只用反向代理无法保留跳转前后不一样的参数,因此需要结合使用。
先用rewrite重写站内域名后面的路径部分及参数,再反代到需要跳转的域名。
如果没有地址栏保持不变这个硬性要求,可以简单粗暴的直接 return 301 跳转的站外域名,缺点是浏览器地址栏的域名发生了变化,同时还触发了用户端(浏览器)301/302重定向。
配置如下:
location /api/ {
if ($args ~* ^(.*)ver=c){
# rewrite ^/(.*)$ /abc?test=123&config=%2fapi-test/$1 break;
#如果不需要跳转前的参数附加到跳转后的参数,就去掉 $1
rewrite ^/(.*)$ /abc?test=123&config=%2fapi-test break;
proxy_pass https://www.test.test;
}
}
实际效果会是这样:
地址栏保持不变,仍是原来的域名及其路径和参数, www.example.com/api/?ver=c
,展现的内容实际却是 www.test.test/abc?test=123&config=%2fapi-test
这个页面的内容
按F12查看网络请求,只产生了一次访问请求,http状态码为 200,并未有 301/302等其他状态码,对客户端完全透明无感知!
另外我这里踩了个坑,涉及到反向代理时,建议谷歌浏览器新建一个无痕窗口(快捷键 Ctrl + Shift + N)来测试,避免缓存等奇奇怪怪的因素导致调试时发现页面万年不变。
在Firefox v91/chrome(Android webview)v93 上测试正常实现。
nginx 后台日志显示了也只显示了一次请求记录,返回 200 状态码 (nginx默认日志级别不记录内部重定向类型,即 rewrite )