Are headers set in the server block inherited to all location blocks

I am seeing strange behavior using includes. For example, if I request a
javascript file (ending in .js) the headers set globally in the server
block
are not set. I was under the impression that if you set headers in the
server block, ALL location blocks below inherit those headers.

See the following:

server {

add_header Strict-Transport-Security max-age=31556926;
add_header X-XSS-Protection “1; mode=block”;
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;

include expires.conf;

}

expires.conf

location ~* .(?:ico|js|css|gif|jpe?g|png|xml)$ {
expires 7d;
add_header Pragma public;
add_header Cache-Control “public, must-revalidate, proxy-revalidate”;
}

When requesting a .js file, the Pragma and Cache-Control headers are
set,
but all the headers set in the base server block are not. What is the
fix
here?

Posted at Nginx Forum:

On Wed, Feb 05, 2014 at 01:49:59AM -0500, justink101 wrote:

Hi there,

I was under the impression that if you set headers in the
server block, ALL location blocks below inherit those headers.

No.

Can you say where you got that impression? Perhaps documentation can be
clarified or corrected.

The request is handled in one location block.

Only the configuration in, or inherited into, that location block,
matters.

Configuration in the location block overrides anything that might
otherwise
have been inherited.

location ~* .(?:ico|js|css|gif|jpe?g|png|xml)$ {
expires 7d;
add_header Pragma public;
add_header Cache-Control “public, must-revalidate, proxy-revalidate”;

“add_header” here means that no “add_header” directives are inherited –
only these two apply.

When requesting a .js file, the Pragma and Cache-Control headers are set,
but all the headers set in the base server block are not.

That is working as intended.

What is the fix here?

If you want configuration in the location block, put all of the
configuration in the location block.

f

Francis D. [email protected]

Hello!

On Wed, Feb 05, 2014 at 01:33:34PM +0000, Francis D. wrote:

clarified or corrected.
It looks like add_header documentation doesn’t have our usual
clause for array-like directives, and something like this should
be helpful:

— a/xml/en/docs/http/ngx_http_headers_module.xml
+++ b/xml/en/docs/http/ngx_http_headers_module.xml
@@ -56,6 +56,14 @@ the response code equals 200, 201, 204,
A value can contain variables.

+
+There could be several add_header directives.
+These directives are inherited from the previous level if and
+only if there are no
+add_header
+directives defined on the current level.
+
+


Maxim D.
http://nginx.org/

Gosh that is horrible that I have to copy and paste shared headers in
the
server block, to all location blocks. Is this a conscious decision? This
makes maintainability very difficult as i have to do something like:

# shared_headers.conf
add_header  Alternate-Protocol 443:npn-spdy/3;
add_header Strict-Transport-Security max-age=31556926;
add_header X-XSS-Protection "1; mode=block";
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;

# expires.conf
location ~* \.(?:ico|css|gif|jpe?g|png|xml)$ {
  include shared_headers.conf;

  expires 7d;
  add_header Pragma public;
  add_header Cache-Control "public, must-revalidate, proxy-revalidate";
}

server {
    ...
    location ^~ /icons {
        include shared_headers.conf;

        add_header Access-Control-Allow-Origin *;
    }

     location ^~ /docs {
        include shared_headers.conf;

        auth_basic "Docs";
        auth_basic_user_file /etc/nginx/auth/docs.htpasswd;
     }

     location ^~ /actions {
          include shared_headers.conf;

          add_header Access-Control-Allow-Origin 
https://www.mydomain.com;
     }
}

Or, is there a better way to do this?

Posted at Nginx Forum:

On Wed, Feb 05, 2014 at 05:52:21PM +0400, Maxim D. wrote:

On Wed, Feb 05, 2014 at 01:33:34PM +0000, Francis D. wrote:

Hi there,

Can you say where you got that impression? Perhaps documentation can be
clarified or corrected.

It looks like add_header documentation doesn’t have our usual
clause for array-like directives, and something like this should
be helpful:

I’m not sure where the best place for it is; but I’d suggest not putting
this on every directive, but only marking the few that don’t follow the
common inheritance rules.

And then have an obvious document which describes what the common
inheritance rules are.

It would probably be something like the content linked from
August 2012 - Martin Fjordvald but could be simplified to
“inheritance is per-directive, and is all or nothing. The following are
‘nothing’; the rest are ‘all’. Exceptions are noted in the per-directive
documentation (and possibly listed here too).”

In the blog above, it indicates that “Action” directives do not inherit
– I don’t know if that’s a useful distinction that could be made in
the documentation; it would presumably be extra work to ensure that
every directives is categorised as “inherit all”, “inherit none”, or
“exception”, and I can’t tell whether the benefit would be worth the
cost.

+These directives are inherited from the previous level if and
+only if there are no
+add_header
+directives defined on the current level.

To me, that’s not special for add_header – that’s common to all
inheriting directives bar the few exceptions (root/alias, allow/deny,
and xslt_param/xslt_string_param in stock nginx).

Maybe it is easier to put it in all directive documentation, though,
if that’s what people are more likely to read.

I won’t be the one doing the work, so I’m not in the right place to
judge what work should be done :slight_smile:

f

Francis D. [email protected]

If its a repetitive block you could use an external file and a single
include line.
http://nginx.org/en/docs/ngx_core_module.html#include

Posted at Nginx Forum:

On Wed, Feb 05, 2014 at 10:55:19AM -0500, justink101 wrote:

Hi there,

Gosh that is horrible that I have to copy and paste shared headers in the
server block, to all location blocks. Is this a conscious decision? This

It’s nginx. It makes it straightforward to see what configuration
applies
to a specific request.

Copy-paste isn’t the only way to create the config file.

makes maintainability very difficult as i have to do something like:

I confess I don’t see how it makes maintainability difficult.

If it matters, could you explain?

(It may not matter, of course.)

You can use the nginx directive “include” to refer to another file, as
you do here; or you could use your macro-processing language of choice
to turn your preferred input format into the desired nginx.conf.

server {

If you use

include shared_headers.conf;

at server level, then you only need to repeat it in locations where you
want different headers added.

 location ^~ /docs {
    include shared_headers.conf;

    auth_basic "Docs";
    auth_basic_user_file /etc/nginx/auth/docs.htpasswd;
 }

So you wouldn’t need it there, for example.

 location ^~ /actions {
      include shared_headers.conf;

      add_header Access-Control-Allow-Origin https://www.mydomain.com;
 }

But you would need it there.

f

Francis D. [email protected]

Hello!

On Wed, Feb 05, 2014 at 03:10:03PM +0000, Francis D. wrote:

be helpful:

I’m not sure where the best place for it is; but I’d suggest not putting
this on every directive, but only marking the few that don’t follow the
common inheritance rules.

And then have an obvious document which describes what the common
inheritance rules are.

Having some generic description of directive inheritance is
certainly a plus (just in case, it likely should be in
/syntax.xml, which currently only contains some basics about size
and time units and needs to be actually written), but it’s yet to
find somebody who’ll sign up for this work.

On the other hand, writing this information explicitly for
array-like directives matches our current practice and seems to
help a lot. Especially keeping in mind that there are only a few
array-like directives where inheritance is important, and most of
them already have the clause in question.

[…]


Maxim D.
http://nginx.org/