Lesson 8 / 25

URIs, Timeouts, Buffering and WebSockets

Get proxy_pass URI rewriting, timeouts and WebSocket upgrades right.

The details that cause outages

URI handling: if proxy_pass has no URI part (proxy_pass http://app;), the original request URI is passed unchanged. If it has a URI part, even just a slash (proxy_pass http://app/;), the part of the request URI matching the location prefix is replaced by it: with location /api/ { proxy_pass http://app/; }, /api/orders becomes /orders upstream. Timeouts: proxy_connect_timeout (establishing the connection, default 60 s, usually far too long), proxy_read_timeout (between two successive reads of the response, default 60 s) and proxy_send_timeout. Buffering: by default NGINX buffers upstream responses, freeing the application quickly even for slow clients; disable it with proxy_buffering off; for streaming responses such as Server-Sent Events. WebSockets need HTTP/1.1 and the Upgrade and Connection headers passed explicitly, plus a long proxy_read_timeout, because hop-by-hop headers are not forwarded by default.

API prefix stripping, SSE and WebSockets

Each location shows one of the common special cases.

map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}

server {
    listen 80;
    server_name app.example.com;

    location /api/ {
        proxy_pass http://api_backend/;         # /api/orders -> /orders upstream
        proxy_connect_timeout 2s;
        proxy_read_timeout 15s;
    }

    location /events/ {
        proxy_pass http://api_backend;          # URI passed unchanged
        proxy_buffering off;                    # stream Server-Sent Events immediately
        proxy_read_timeout 1h;
    }

    location /ws/ {
        proxy_pass http://realtime_backend;
        proxy_http_version 1.1;
        proxy_set_header Upgrade    $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
        proxy_read_timeout 1h;                  # idle WebSockets must not be cut at 60 s
    }
}

A receptionist forwarding calls

The receptionist (NGINX) takes every call and forwards it inside. Whether they read out the full extension or drop the department prefix depends on one small instruction, and for long conference calls (WebSockets) they must not hang up after a minute of silence.

Quick check: With `location /api/ { proxy_pass http://backend/; }`, what URI does the backend receive for /api/users?

  • /api/users
  • /backend/users
  • /
  • /users
Answer

/users — Because proxy_pass includes a URI (/), the matched /api/ prefix is replaced by /.