Nginx reverse proxy cache revalivation error

nginxreverse-proxy

We have a C/C++ app with an embedded http server. Our http server is very native, does not support ssl or keep-alive connection. It listen on port 5555 and servers static pages. Before serving the page, it gzip the response. It also supports cache validation with Etags. Depending on the If-None-Match value it sends 304 Not Modifed. It work fine if we redirect our browser to some-ip:5555. Sample request and response header is as follows

Response Headers
Cache-Control   max-age=3600, must-revalidate
Content-Encoding    gzip
Expires Wed, 15 May 2013 07:18:08 GMT

Request Headers
Accept  */*
Accept-Encoding gzip, deflate
Accept-Language en-us,en;q=0.5
Cache-Control   max-age=0
Connection  keep-alive
Host    127.0.0.1:5555
If-Modified-Since   Tue, 08 May 2012 08:48:53 GMT
If-None-Match   "1336466933_85925"
Referer http://127.0.0.1:5555/mlogin.html
User-Agent  Mozilla/5.0 (X11; Linux x86_64; rv:10.0.4) Gecko/20120425 Firefox/10.0.4

Response Headers From Cache
Cache-Control   max-age=3600, must-revalidate
Content-Encoding    gzip
Content-Length  29832
Content-Type    application/x-javascript
Etag    "1336466933_85925"
Expires Wed, 15 May 2013 07:18:08 GMT
Last-Modified   Tue, 08 May 2012 08:48:53 GMT

Now when the same setup is tried with nginx reverse proxy, it gives 502 Bad Gateway for all those page which tries to revalidate cache. It works fine for all page whose Cache-Control no-cache. Our nginx configuration is as follows

user  nginx;
worker_processes  1;

error_log  /var/log/nginx/error.log debug;
pid        /var/run/nginx.pid;

events {
    worker_connections  1024;
}

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;
    keepalive_requests 0;
    keepalive_timeout  0;

    server {
   server_name _;
   listen 80;
   location / {
        proxy_pass http://127.0.0.1:5555;
        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;
        proxy_max_temp_file_size 0;

        client_max_body_size       10m;
        client_body_buffer_size    128k;

        proxy_connect_timeout      90;
        proxy_send_timeout         90;
        proxy_read_timeout         90;

        proxy_buffer_size          4k;
        proxy_buffers              4 32k;
        proxy_busy_buffers_size    64k;
        proxy_temp_file_write_size 64k;

   }
}

The response and request header then is

Response Headers
Connection  close
Content-Length  172
Content-Type    text/html
Date    Tue, 15 May 2012 08:46:31 GMT
Server  nginx/1.2.0

Request Headers
Accept  text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding gzip, deflate
Accept-Language en-us,en;q=0.5
Cache-Control   max-age=0
Connection  keep-alive
Host    127.0.0.1
If-Modified-Since   Tue, 08 May 2012 08:48:53 GMT
If-None-Match   "1336466933_85925"
User-Agent  Mozilla/5.0 (X11; Linux x86_64; rv:10.0.4) Gecko/20120425 Firefox/10.0.4

In nginx error log we get this error

2012/05/15 14:16:31 [error] 18832#0: *177 upstream prematurely closed connection while reading response header from upstream, client: 127.0.0.1, server: _, request: "GET /lib/jquery-1.5.2.min.js?v=1330852144 HTTP/1.1", upstream: "http://127.0.0.1:5555/lib/jquery-1.5.2.min.js?v=1330852144", host: "127.0.0.1"

Can anyone suggest what is going wrong? Thanks in advance.

Best Answer

Probably, your http-server breaks HTTP protocol somehow, e.g. doesn't send additional CRLF after last header.