Too Cool for Internet Explorer

nginx tips: adding arbitrary output to a response


A while ago i wrote about how to use nginx as a proxy to do cookie based redirects. We use this functionality at work to provide easy access and view the progress of development of each developer.

I thought it would be nice to have the information, of which developers machine you currently have access to, right on the website. But i always disliked to put functionality to accomplish this inside the framework or even the app itself or have to install / modify some special configuration on each developers machine. I always wanted my proxy to do this kind of work. ... And nginx can.

It's the substitution module of nginx, that can replace arbitrary text in a http response. Nginx must be compiled with the option --with-http_sub_module configured.

The following rows show how to fill a variable $name with the name of the developer we are accessing the machine of. The statement sub_filter defines the search pattern as first parameter and the replace string as second parameter -- very easy, isn't it?

set $name ""
if ($http_cookie ~* "(; )?devredirect=([^;]+)") {
    set $name $2;
}
sub_filter      "</body>"       "<div style='position: fixed; 
    left: 0; top: 0; font-weight: bold; padding: 5px; color: #000; 
    background-color: rgb(235,58,0);'>devredirect: ${name}</div>
    </body>";

The following rows show the part of the proxy configuration with the inserted substitution filter:

server {
    listen          80;
    server_name     .clipdealer.devcenter.int;

    proxy_redirect          off;
    proxy_set_header        Host            $host;
    proxy_set_header        X-Real-IP       $remote_addr;
    proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;

    location / {
        set $name ""
        if ($http_cookie ~* "(; )?devredirect=([^;]+)") {
            set $name $2;
        }
        sub_filter      "</body>"       "<div style='position: fixed; 
            left: 0; top: 0; font-weight: bold; padding: 5px; 
            color: #000; background-color: rgb(235,58,0);'>
            devredirect: ${name}</div></body>";

        if ($http_cookie ~* "(; )?devredirect=harald") {
            proxy_pass              http://10.0.0.20;
            break;
        }
        ...
    }
    ....
}


cookie based redirect mit nginx


Vor einiger Zeit habe ich einen Tip beschrieben, wie man einen cookie-based redirect mit dem LightTPD konfigurieren kann. Das Problem an der Sache ist für mich, dass das für diesen Zweck verwendete Modul mod_proxy von LightTPD in dem von mir eingesetzen Entwicklungszweig (1.4.x) nicht SSL kompatibel ist und dementsprechend HTTPS Verbindungen fehlschlagen.

Seit einiger Zeit schon habe ich den Web- und (Reverse-) Proxy-Server nginx im Auge. Auch mit diesem Server ist es möglich einen Redirect einzurichten, so wie ich ihn brauche. Und: nginx unterstützt an dieser Stelle SSL!


server {
    listen          80;
    server_name     *.devcenter.int;

    proxy_redirect      off;
    proxy_set_header    Host            $host;
    proxy_set_header    X-Real-IP       $remote_addr;
    proxy_set_header    X-Forwarded-For $proxy_add_x_forwarded_for;

    location / {
        if ($http_cookie ~ "(; )?devredirect=harald") {
            proxy_pass              http://10.0.0.20;
            break;
        }
        if ($http_cookie ~ "(; )?devredirect=markus") {
            proxy_pass              http://10.0.0.22;
            break;
        }

        ...
    }
}


server {
    listen          443;
    server_name     ....devcenter.int;

    ssl                     on;
    ssl_certificate         /etc/nginx/....crt;
    ssl_certificate_key     /etc/nginx/....key;

    proxy_redirect      off;
    proxy_set_header    Host            $host;
    proxy_set_header    X-Real-IP       $remote_addr;
    proxy_set_header    X-Forwarded-For $proxy_add_x_forwarded_for;

    location / {
        if ($http_cookie ~ "(; )?devredirect=harald") {
            proxy_pass              https://10.0.0.20;
            break;
        }
        if ($http_cookie ~ "(; )?devredirect=markus") {
            proxy_pass              https://10.0.0.22;
            break;
        }

        ...
    }
}