Add_header not allowed in server if blocks?

I’m trying to add support for google chrome frame to our nginx config
the simple way would be to include a fragment in each server block which
looks something like:

    if ( $http_user_agent ~ chromeframe ) {
        add_header X-UA-Compatible "chrome=1";
    }

The problem is for some reason add_header isn’t allowed in server-if
blocks on location-if blocks. I can’t see or think of a reason why this
shouldn’t be allowed?

So I tried adding it and it seems to work without a problem. The
following patch, made against 0.8.40, adds server if block support for
both expires and add_header.

--- src/http/modules/ngx_http_headers_filter_module.c.orig  2010-06-14 
23:48:58.000000000 +0100
+++ src/http/modules/ngx_http_headers_filter_module.c   2010-06-14 
23:49:27.000000000 +0100
@@ -79,7 +79,7 @@

     { ngx_string("expires"),
       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
-                        |NGX_CONF_TAKE12,
+                        |NGX_HTTP_SIF_CONF|NGX_CONF_TAKE12,
       ngx_http_headers_expires,
       NGX_HTTP_LOC_CONF_OFFSET,
       0,
@@ -87,7 +87,7 @@

     { ngx_string("add_header"),
       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
-                        |NGX_CONF_TAKE2,
+                        |NGX_HTTP_SIF_CONF|NGX_CONF_TAKE2,
       ngx_http_headers_add,
       NGX_HTTP_LOC_CONF_OFFSET,
       0,

Posted at Nginx Forum:
http://forum.nginx.org/read.php?2,98202,98202#msg-98202

Hello!

On Mon, Jun 14, 2010 at 07:04:21PM -0400, steveh wrote:

I’m trying to add support for google chrome frame to our nginx
config the simple way would be to include a fragment in each
server block which looks something like:

if ( $http_user_agent ~ chromeframe ) {
    add_header X-UA-Compatible "chrome=1";
}

Just adding X-UA-Compatible unconditionally should be sufficient,
but if you really want to return it to chrome frame only, try
something like this:

set $tt "";

if ($http_user_agent ~ chromeframe) {
    set $tt "chrome=1";
}

add_header X-UA-Compatible $tt;

Note well: add_header used in location would reset inherited
add_header directives (usual array inheritance rules apply), so
you have to repeat add_header in such locations (if any).

The problem is for some reason add_header isn’t allowed in
server-if blocks on location-if blocks. I can’t see or think of
a reason why this shouldn’t be allowed?

Actually, the real question is “why it’s allowed in ‘if in
location’ blocks”. The answer seems to be “uh, it was a mistake”.
See here for details:

http://wiki.nginx.org/IfIsEvil

So I tried adding it and it seems to work without a problem. The
following patch, made against 0.8.40, adds server if block
support for both expires and add_header.

You didn’t tested it well enough. It does nothing but removes
config parsing error.

Maxim D.

Hmm ok so it seems I was bitten by some unpredictable behaviour in gcf
and this doesn’t actually work.

Setting just: add_header X-UA-Compatible “chrome=1”; in the server block
or in an if within every location-if works but that’s not ideal.

Any ideas why add_header within a server-if doesn’t work as expected?

Posted at Nginx Forum:
http://forum.nginx.org/read.php?2,98202,98224#msg-98224

Thanks for that, helps a lot.

My initial test which made me think it was working, when it wasn’t,
seems to be due chrome frame some how caching the result of headers. So
if you load a page once which triggers chrome mode due to the correct
header in place, if you remove said header and reload it still loads in
chrome frame. Will be down to how refresh works I expect. You live and
learn :slight_smile:

Thanks again.

Posted at Nginx Forum:
http://forum.nginx.org/read.php?2,98202,98239#msg-98239