你需要处理的问题需要在Web服务器层面解决。因此,我创建了两个服务器,一个使用Apache,另一个使用Nginx来解决这个问题。测试命令:
curl -H "X: Y" -H "X: Z" http://localhost:8088/router.php | jq
Apache
使用 Apache 执行时,输出结果如下:
{
"HEADERS": {
"Host": "localhost:8088",
"User-Agent": "curl/7.47.0",
"Accept": "*/*",
"X": "Y, Z"
}
}
正如您所看到的,我们向apache传递了两个头文件,apache使用
,
将它们组合在一起。如果我们改变第一个头文件已经包含
,
,它仍然可以正常工作。
$ curl -H "X: Y, A" -H "X: Z" http:
{
"HEADERS": {
"Host": "localhost:8088",
"User-Agent": "curl/7.47.0",
"Accept": "*/*",
"X": "Y, A, Z"
}
}
Nginx
现在在 Nginx 上发送同样的请求会产生以下结果:
{
"HEADERS": {
"X": "Z",
"Accept": "*/*",
"User-Agent": "curl/7.47.0",
"Host": "localhost"
}
}
现在,Nginx确实会将这些标头发送到PHP-FPM,但PHP-FPM不会将这些重复的标头合并为一个。因此,在脚本中,您只会得到最新的标头。
编辑-1:使用fastcgi_param合并
感谢@AronCederholm指出,通过指定FASTCGI_PARAM可以实现合并。
我最初尝试了相同的方法,但结果是空白标头。我曾尝试添加
fastcgi_param X-Forwarded-For $http_x_forwarder_for
刚才在阅读他的消息后,我意识到我的配置文件中有一个错别字。应该是
。
fastcgi_param X-Forwarded-For $http_x_forwarded_for
在这个更改之后,标题可以正常工作。但是它不会出现在getallheaders()中。如下响应所示,它将通过$_SERVER[]
可用。
$ curl -v -H 'X-Forwarded-For: 127.0.0.1' -H 'X-Forwarded-For: 8.8.8.8' http:
{
"HEADERS": {
"X-Forwarded-For": "8.8.8.8",
"Accept": "*/*",
"User-Agent": "curl/7.47.0",
"Host": "localhost"
},
"SERVER": {
"USER": "vagrant",
"HOME": "/home/vagrant",
"HTTP_X_FORWARDED_FOR": "8.8.8.8",
"HTTP_ACCEPT": "*/*",
"HTTP_USER_AGENT": "curl/7.47.0",
"HTTP_HOST": "localhost",
"X-Forwarded-For": "127.0.0.1, 8.8.8.8",
原始答案
很不幸,我没有找到任何适用于Nginx或PHP-FPM的设置或插件,可以将重复的标头合并为一个。而且你无法在PHP级别处理这种情况,因为你永远无法看到原始标头。
可能的解决方案
- 将Apache放在Nginx前面。让nginx监听unix套接字,并使用apache反向代理请求到nginx
- 用Apache替换Nginx
- 创建一个Nginx插件来合并标头。以下两个项目应该能帮助你入门
https://github.com/giom/nginx_accept_language_module
https://github.com/openresty/headers-more-nginx-module
X-Forwarded-For: 1.2.3.4,1.2.3.5
。 - Charlotte Dunois