Nginx反向代理add_header always指令部分场景失效问题求助
Nginx反向代理add_header always指令部分场景失效问题求助
大家好,我碰到一个Nginx配置的诡异问题,想请教下各位大佬:
当上游服务器返回非HTTP 200 OK的响应时,hostnameb.example.org的请求会丢失X-custom-server-info头,但hostnamea.example.org的响应是正常的(包含这个头)。有没有大佬知道原因或者怎么修复?
我的Nginx配置如下:
worker_processes auto; worker_rlimit_nofile 8192; pid /opt/bitnami/nginx/tmp/nginx.pid; events { worker_connections 4096; } http { include /opt/bitnami/nginx/conf/mime.types; add_header X-custom-server-info "someinfo" always; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Forwarded ""; proxy_http_version 1.1; client_max_body_size 10m; client_body_buffer_size 128k; proxy_connect_timeout 180; proxy_send_timeout 180; proxy_read_timeout 180; proxy_buffers 32 4k; proxy_set_header Host $host; proxy_set_header X-Forwarded-Host $host; #proxy_set_header X-Forwarded-Proto $scheme; #proxy_set_header X-Forwarded-Port $server_port; proxy_set_header X-Forwarded-Proto https; proxy_set_header X-Forwarded-Port 443; server_tokens off; sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; types_hash_max_size 2048; server_names_hash_bucket_size 128; # this seems to be required for some vhosts default_type application/octet-stream; resolver dns-default.openshift-dns.svc.cluster.local valid=300s; server { listen 8081; server_name hostnamea.example.org; set $bff "http://bff.project.svc.cluster.local"; location / { proxy_pass $bff; } } server { listen 8081; server_name hostnameb.example.org; set $bff "http://bff.project.svc.cluster.local"; location / { proxy_pass $bff; add_header Access-Control-Allow-Origin https://external.example.org always; add_header Access-Control-Allow-Credentials true always; } } log_format upstreamlog '[$time_local] "$request" UA:"$http_user_agent"'; access_log /opt/bitnami/nginx/logs/access.log upstreamlog; error_log /opt/bitnami/nginx/logs/error.log; }
问题分析与解决方案
这其实是Nginx add_header指令的一个特性:当在子块(比如location)中定义了add_header后,父块(这里是http块)的add_header指令会被覆盖,即使你加了always参数也一样。
具体来说:
hostnamea.example.org的location块里没有自定义的add_header,所以会自动继承http块的X-custom-server-info头,加上always参数,不管上游返回什么状态码都能正常生效。hostnameb.example.org的location块里添加了两个CORS相关的add_header,这时候http块的add_header就不会被继承了,所以只有这两个CORS头会被添加,X-custom-server-info自然就丢失了,不管上游返回200还是非200状态。
修复方法很简单,有两种思路:
- 把
X-custom-server-info头也加到hostnameb.example.org的location块里,确保所有需要的头都被显式定义:
server { listen 8081; server_name hostnameb.example.org; set $bff "http://bff.project.svc.cluster.local"; location / { proxy_pass $bff; add_header X-custom-server-info "someinfo" always; add_header Access-Control-Allow-Origin https://external.example.org always; add_header Access-Control-Allow-Credentials true always; } }
- 如果CORS头适用于整个
server块,可以把它们移到server层级,这样location块就不会覆盖父级的add_header,http块的X-custom-server-info就能正常继承:
server { listen 8081; server_name hostnameb.example.org; add_header Access-Control-Allow-Origin https://external.example.org always; add_header Access-Control-Allow-Credentials true always; set $bff "http://bff.project.svc.cluster.local"; location / { proxy_pass $bff; } }
两种方法都能解决问题,你可以根据自己的配置场景选择合适的方式。
备注:内容来源于stack exchange,提问作者tomas
相关产品推荐
相关产品推荐

