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

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状态。

修复方法很简单,有两种思路:

  1. 把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;
    }
}
  1. 如果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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.22 15:38:14