【啰嗦两句】
也不知道为啥,我仅仅想在Nginx的反向代理中使用自己定义的“x-api-key”做Header参数,却发现会被忽略,网上搜的资料都是说用“proxy_set_header”,却只愿意介绍最基本的几个参数,你懂的,那些资料抄来抄去,没一个能用。
好在通过个别文章的只言片语,找到了答案,本文专门只讲自定义Header参数,其他请自行搜索。
【事情起源】
我有个后端框架,做API接口用,平时都是用Tomcat做HTTPS解析,但是近期因为VUE要对接,静态和动态服务想区分不同服务器,于是用上Nginx做区分,自然是很好很好用的了。架构如下图,这样的调整也实在太常见,没什么可看的了。
而Nginx的反向代理配置如下:
location /api {
proxy_pass https://192.168.1.88/myServer;
proxy_set_header Host $host;
proxy_set_header X-Real-Ip $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
我的框架靠请求头的Header["x-api-key"]区分客户端,里面包含了token,而这个x-api-key并不是标准Header。也就是说,C段和浏览器端请求时是带来Header["x-api-key"]=ABCDEF...这一串token。
调试发现浏览器请求有x-api-key,后端却收不到x-api-key,难道被Nginx吃了?
【排查之路】
于是靠关键字“nginx自定义Header”的关键字,搜了一堆资料都是在讲用诸如:
proxy_set_header X-Custom-Header myvalue;
或
proxy_set_header X-Custom-Header $myvalue;
实测第一个myvalue传递给tomcat,收到的是字符串“myvalue”。第二个直接出错,nginx起都起不来,没戏(log显示:unknown "myvalue" variable)。
好吧,字符串myvalue自然不是动态想要的效果,那就从$myvalue下手,$这个符号好理解,应该是内置变量的意思,可是资料都只是提一嘴myvalue,这个myvalue变量怎么来的?在哪定义?却没人写过真实案例。搞得我还去分析了nginx内置参数高级应用资料。
后来无意中看到一篇高级应用《Nginx高级配置》,感谢作者,已设链接。清单里面写着内置参数“$http_”,但是也仅仅就这一句话,刚开始都是被忽略过去,只是多搜几遍才注意到他。
可是这句话想表达什么呢?也没个示例,哪里看得懂!看过几遍之后忽然想到是不是要拼接我的变量名称?于是我尝试把配置改为:
location /api {
proxy_pass https://192.168.1.88/myServer;
proxy_set_header Host $host;
proxy_set_header X-Real-Ip $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header x-api-key $http_x-api-key;
}
试过,这回tomcat终于收到x-webapi-key了!然鹅,收到是收到了,却依然不能正确执行接口代码,排查发现奇怪,后端收到的是:
x-webapi-key=-api-key
是有点心凉,但是牛马始终要继续向前的,于是着重分析了一下,发现这里应该有个“$http_x”不见了,说明nginx转换的时候可能有截断行为,那就找找$http_资料先。
经过努力,在这篇文章看到蛛丝马迹《nginx $http_ 详解》,感谢作者,已设链接。文章提到
也就是说,nginx要求把横杠替换成下划线才行。于是试着改一下配置:
location /api {
proxy_pass https://192.168.1.88/myServer;
proxy_set_header Host $host;
proxy_set_header X-Real-Ip $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header x-api-key $http_x_api_key;
}
这次是真的成功了, 后端收到正确的字符串了。
【最终解决方案】
在nginx配置里面的server节点,增加
proxy_set_header 自定义的name $http_自定义name(其中横杠改为下划线)
示例:
proxy_set_header x-api-key $http_x_api_key;
【多说两句Cookie】
如果解决自定义header问题之后,还发现cookie也没有传递,那么有2个细节要注意:
1、没有跨域,则常见资料的配置为:
proxy_set_header Cookie $http_cookie;
2、还是没收到?那可能跨域了例如:
请求的是localhost/api,而转发的是192.168.1.100/server,这里的“api”和“server”就会识别为不同域,想要把配置改为如下:
location /api {
proxy_pass https://192.168.1.88/myServer;
proxy_set_header Host $host;
proxy_set_header X-Real-Ip $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;#传递原始Cookie
proxy_set_header Cookie $http_cookie;#加上设置Cookie的路径,否则跨域后浏览器不存储cookie
proxy_cookie_path /myServer /api;
}
【参考文献】
Nginx高级配置 - hx_ky36 - 博客园
https://juejin.cn/post/7432294106463797267