Opened 3 years ago

Closed 3 years ago

Last modified 3 years ago

#1264 closed defect (invalid)

proxy_set_header directives unable to be set in condition blocks

Reported by: rigrassm@… Owned by:
Priority: minor Milestone:
Component: nginx-module Version: 1.11.x
Keywords: proxy_set_header Cc:
uname -a: Linux xxxx.hostname.tld 4.10.9-100.fc24.x86_64 #1 SMP Mon Apr 10 14:47:56 UTC 2017 x86_64 GNU/Linux
nginx -V: nginx version: nginx/1.11.13


Nginx will not allow the proxy_set_header directive to be used inside of a conditional statement block.

For example:

        server {

		location / {
            	    proxy_buffering off;
            	    proxy_http_version 1.1;
            	    proxy_read_timeout 36000s;
		    proxy_set_header Host $host;
		    proxy_set_header X-Real-IP $remote_addr;
		    proxy_set_header Upgrade $http_upgrade;
		    proxy_set_header Connection "upgrade";
                    if ($subdomain = "plex") {
                        proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
            	        proxy_set_header X-Forwarded-Proto https;
            	        proxy_set_header X-Forwarded-Host $host;
            	        proxy_set_header X-Plex-Client-Identifier  $http_x_plex_client_identifier;
		    if ($subdomain) {
			proxy_pass $proxy_url;

When the directives are set inside the conditional statement, Nginx will fail to reload giving the error below.

2017/05/04 10:45:56 [emerg] 64#64: "proxy_set_header" directive is not allowed here in /etc/nginx/nginx.conf:74

nginx: [emerg] "proxy_set_header" directive is not allowed here in /etc/nginx/nginx.conf:74

Since these conditional statements are in a valid location as specified in the documentation, they should be able to contain directives that would otherwise be allowed if the directives were set outside the conditional block. This is useful in my case as I proxy a number of applications and would like to be able to set headers based on the application I'm proxying to using the conditional statements.

Change History (2)

comment:1 by Maxim Dounin, 3 years ago

Resolution: invalid
Status: newclosed

The "if" directive is a block directive and creates a separate context (or, rather, two separate contexts - "if in server", "if in location"). When a directive is allowed in a specific context, this is explicitly documented. For example, the set directive:

Context: server, location, if

So the set directive is allowed inside server, location, and if blocks.

The proxy_set_header is not allowed inside if blocks, and there are no plans to change this. If you want to pass headers conditionally, consider using proxy_set_header with values set conditionally instead, for example:

# default value is empty
set $x_value "";

if ($arg_test) {
    set $x_value "present only when test argument set";

# the header will be only sent if $x_value is not empty
proxy_set_header X-Header $x_value;

You may also use map to provide a value. Depending on the particular use case it may also be a better idea to use distinct server or location blocks instead.

comment:2 by rigrassm@…, 3 years ago

@mdounin Sorry for the late reply, I just wanted to thank you for the insight(I didn't know about these quirks with if statements) as well as the work around which should work out great for my use case.

Thanks for all yall's hard work!

Note: See TracTickets for help on using tickets.