JSON error page for Nginx

We use the ngx_http_auth_request_module to authenticate requests by calling one of our services. Unfortunately, if the request is rejected, it returns the default 401 error page:

<html>
<head><title>401 Authorization Required</title></head>
<body bgcolor="white">
<center><h1>401 Authorization Required</h1></center>
<hr><center>nginx/1.9.10</center>
</body>
</html>

Which is a bit out of place, when the rest of our responses are JSON. A simple fix is to override it:

server {
    ...
    error_page 401 @401_json;

    location @401_json {
        default_type application/json;
        return 401 '{"error":{"message":"Unauthorised"}}';
    }
}

But remember this will be used for all 401s, not just those from the auth module.

Building nginx with the push stream module on Debian

I’ve been trying out the push stream module for nginx recently. The instructions for building it are pretty clear, but I also wanted all the benefits of installing it as a package with apt-get.

I found this handy guide which outlines the general procedure. First, make sure that the build dependencies for the package are installed:

sudo apt-get build-dep nginx

Then download the package source:

apt-get source nginx

Add the new module to the source tree:

cd nginx-1.2.1/debian/modules
curl -L https://github.com/wandenberg/nginx-push-stream-module/tarball/master | sudo tar zx
mv wandenberg-nginx-push-stream-module-71c511d nginx-push-stream-module

Update the rules file to include the module, and modify the version in the changelog. Then build the package:

dpkg-buildpackage -b

You can now install the required packages:

sudo dpkg -i nginx-common_1.2.1-2.2+wheezy2-push_all.deb nginx-full_1.2.1-2.2+wheezy2-push_amd64.deb nginx_1.2.1-2.2+wheezy2-push_all.deb

Or save them, for use elsewhere. Once the module is installed you need to update the nginx.conf:

    http {
        push_stream_shared_memory_size 256M;
    }

And add a site:

server {
    listen 80;

    location /channels-stats {
        # activate channels statistics mode for this location
        push_stream_channels_statistics;

        # query string based channel id
        push_stream_channels_path               $arg_id;
    }

    location /pub {
        # activate publisher (admin) mode for this location
        push_stream_publisher admin;

        # query string based channel id
        push_stream_channels_path               $arg_id;
    }

    location ~ /sub/(.*) {
        # activate subscriber (streaming) mode for this location
        push_stream_subscriber;

        # positional channel path
        push_stream_channels_path                   $1;
    }
}

You can then test the pub/sub functionality using curl:

Subscribe:
curl -i -N -H "Connection: Upgrade" -H "Upgrade: websocket" -H "Host: localhost" -H "Origin: http://localhost" http://localhost/sub/channel1

Publish:
curl -s 'http://localhost/pub?id=channel1' -d '{"foo": "bar"}'