I'm trying to setup a WebSocket endpoint on my Rails API using Nginx and Puma.
What I have (working but ugly)
The following Nginx configuration works fine, however I feel like I could use something more clever to avoid duplication on both @puma
and @puma_ws
named locations:
upstream puma {
server unix:///path/to/socket.sock;
}
server {
listen 80;
server_name example.com;
root /var/www/public;
location / {
try_files $uri/index.html $uri @puma;
}
location ~ ^/api/websocket {
try_files $uri/index.html $uri @puma_ws;
}
location @puma {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://puma;
}
location @puma_ws {
# These two lines are the only difference compared to @puma
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://puma;
}
}
Note: I'm using a regex for the WS location (
~ ^/api/websocket
) because in my actual use case I need to have more than one WS endpoints. I simplified for the sake of this post's simplicity.
Initial idea
My first idea was to have only one named location @puma
, which would have a nested location with the regex that would only add the two needed proxy_set_header
.
That way I would have only one try_files
with the only @puma
named location, which would add the headers by itself using a nested location
However afaik it is not possible to have nested location
block in a named location.
Do you have a better idea to add those headers based on a test on the actual URI?
Thanks!