Polkadot and other Substrate-based chain nodes supports JSON RPC over HTTP and over WebSocket on ports 9933 and 9944 individually.

However, according to the WebSocket handshake, we can determine if the client is requesting WebSocket or other HTTP resource by the header Upgrade: websocket.

Here’s a little trick in Nginx to reverse proxy both 9933 (HTTP) and 9944 (WebSocket) with the same host, same port, and same path / location.

map $http_upgrade $upstream_backend {
    # proxy to 9944 if the client wanted to upgrade to a websocket conn
    websocket http://127.0.0.1:9944;
    # proxy to 9333 otherwise
    default http://127.0.0.1:9933;
}

server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name _;

    location / {
        proxy_pass $upstream_backend;
    }
}