I'm having a difficult time getting add_header
to work when try_files
is used to send requests to a named location which specifies a backend with proxy_pass
.
Basically, I want to override Content-Type
for a specific set of URIs, but don't want to use a map
to set a variable for it (since I'd like the types
and mime.types
mechanism to continue working as is), nor to set an extension on the URIs and add more types
declarations.
Here's a simplified version of my 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;
}
}
}
I'm using ngx_aws_auth here, but I don't think that should matter.
The behavior I've seen with nginx 1.16.0 is that Content-Type
is not returned at all; not for the /textfile
location where I expect text/plain
, nor for any other URL where I expect text/html
because of the default_type
at the http
level. If I remove the proxy_hide_header Content-Type
line then I simply get the backend's header, which is what I want to override.
I understand the frankly unintuitive behavior of add_header
where headers aren't inherited from a higher level if add_header
is specified at the current level, which I don't think is happening here, but I also tried moving all header directives to a standalone .conf file and including it everywhere, and I still get the same behavior.
I also tried using the headers-more module, with no difference.
What am I missing, Server Fault?
Thanks!
Best Answer
The solution is to use an additional named block to have a custom header for all the requests pass through it. The code in the original question didn't work because add_header is effective only on the last matched location block. If a request passes through multiple location blocks, it doesn't pick up
add_header
directive on the passed location blocks. Nginx only considers or looks foradd_header
in the last matched location block. In this case, the named location block is the last matched location block. I hope that clarifies why the original code didn't work as expected.