具有命名位置的 nginx 反向代理:如何覆盖后端标头?

具有命名位置的 nginx 反向代理:如何覆盖后端标头?

当我使用 向指定后端的命名位置发送请求时,我很难开始add_header工作。try_filesproxy_pass

基本上,我想覆盖Content-Type一组特定的 URI,但不想使用map为其设置变量(因为我希望typesmime.types机制继续按原样工作),也不想在 URI 上设置扩展并添加更多types声明。

这是我的简化版本nginx.conf

http {
    include       mime.types;
    default_type  text/html;
    charset       utf-8;

    server {
        listen 80;

        location @backend {
            rewrite ^ /proxy$uri break;
            proxy_pass https://backend;
            proxy_intercept_errors on;

            aws_access_key ***;
            aws_secret_key ***;
            s3_bucket ***;
            chop_prefix /proxy;

            proxy_set_header Authorization $s3_auth_token;
            proxy_set_header x-amz-date $aws_date;
            proxy_hide_header Content-Type;
        }

        location / {
            try_files false @backend;
        }

        location ~ /(textfile|anothertextfile)$ {
            try_files false @backend;
            add_header Content-Type 'text/plain' always;
            # This has no effect either
            # default_type text/plain;
        }
    }
}

我在用着ngx_aws_auth这里,但我不认为那有什么关系。

我在 nginx 1.16.0 中看到的行为是Content-Type根本没有返回;不是/textfile我期望的位置text/plain,也不是我期望的任何其他 URL,text/html因为处于default_type级别http。如果我删除该proxy_hide_header Content-Type行,那么我只会获取后端的标头,这就是我想要覆盖的。

add_header我理解如果在当前级别指定了标题,则标题不会从更高级别继承的坦率的非直观行为add_header,我不认为这里会发生这种情况,但我也尝试将所有标题指令移动到独立的 .conf 文件并将其包含在所有地方,但我仍然得到相同的行为。

我也尝试过使用标题-更多模块,没有区别。

我遗漏了什么?服务器故障?

谢谢!

答案1

解决方案是使用额外的命名块,为通过它的所有请求设置自定义标头。原始问题中的代码不起作用,因为添加标题仅对最后一个匹配的位置块有效。如果请求经过多个位置块,它不会add_header在传递的位置块上拾取指令。Nginx 仅在最后一个匹配的位置块中考虑或查找add_header。在这种情况下,命名的位置块是最后一个匹配的位置块。我希望这能解释为什么原始代码没有按预期工作。

http {
    include       mime.types;
    default_type  text/html;
    charset       utf-8;

    server {
        listen 80;

        location @backend {
            rewrite ^ /proxy$uri break;
            proxy_pass https://backend;
            proxy_intercept_errors on;

            aws_access_key ***;
            aws_secret_key ***;
            s3_bucket ***;
            chop_prefix /proxy;

            proxy_set_header Authorization $s3_auth_token;
            proxy_set_header x-amz-date $aws_date;
            proxy_hide_header Content-Type;
        }

        location @plain_backend {
            rewrite ^ /proxy$uri break;
            proxy_pass https://backend;
            proxy_intercept_errors on;

            aws_access_key ***;
            aws_secret_key ***;
            s3_bucket ***;
            chop_prefix /proxy;

            proxy_set_header Authorization $s3_auth_token;
            proxy_set_header x-amz-date $aws_date;
            proxy_hide_header Content-Type;

            add_header Content-Type 'text/plain' always;
        }

        location / {
            try_files false @backend;
        }

        location ~ /(textfile|anothertextfile)$ {
            try_files false @plain_backend;
        }
    }
}

相关内容