Search code examples
httpnginxproxyhttpserverresolver

Nginx resolver with proxy pass and variables not functioning


I would like to setup a DNS resolver so when a host in the upstream is not yet resolved (e.g. DNS server is up yet), the Nginx server will not crash. I am passing the URLs as environment variables.

Previous configuration:

server {
  listen 80;

  gzip on;
  gzip_disable "msie6";

  gzip_vary on;
  gzip_proxied any;
  gzip_comp_level 6;
  gzip_buffers 16 8k;
  gzip_http_version 1.1;
  gzip_min_length 0;
  gzip_types text/plain application/javascript text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/vnd.ms-fontobject application/x-font-ttf font/opentype;

  location / {
    root   /usr/share/nginx/html;
    index  index.html index.htm;
    try_files $uri $uri/ /index.html;
  }

  location /foo-server/socket.io {
    proxy_pass ${FOO_SERVER_SOCKET_IO_URL}/socket.io;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection 'upgrade';
    proxy_set_header Host $host;
    proxy_cache_bypass $http_upgrade;
  }

  ...

  error_page 500 502 503 504 /50x.html;

  location = /50x.html {
    root  /usr/share/nginx/html;
  }
}

And the modified version:

server {
  listen 80;
  resolver 127.0.0.11 valid=60s ipv6=off;
  resolver_timeout 10s;

  gzip on;
  gzip_disable "msie6";
  gzip_vary on;
  gzip_proxied any;
  gzip_comp_level 6;
  gzip_buffers 16 8k;
  gzip_http_version 1.1;
  gzip_min_length 0;
  gzip_types text/plain application/javascript text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/vnd.ms-fontobject application/x-font-ttf font/opentype;

location / {
    root   /usr/share/nginx/html;
    index  index.html index.htm;
    try_files $uri $uri/ /index.html;
  }

  location /foo-server/socket.io {
    set $foo_server_socket_io $FOO_SERVER_SOCKET_IO_URL;
    proxy_pass $foo_server_socket_io/socket.io;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection 'upgrade';
    proxy_set_header Host $host;
    proxy_cache_bypass $http_upgrade;
  }

  ...

  error_page 500 502 503 504 /50x.html;

  location = /50x.html {
    root  /usr/share/nginx/html;
  }
}

The Nginx server log part:

2024-02-13 16:05:35 192.168.65.1 - - [13/Feb/2024:15:05:35 +0000] "GET /foo-server/socket.io/?EIO=4&transport=polling&t=OsZ086l HTTP/1.1" 404 147 "http://localhost:3000/foo-path" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36" "-"

In the original version, if the FOO_SERVER_SOCKET_IO_URL is not set/undefined, the server crashes. In the modified version it does not, but I get 404 for the connection request.

  • added the resolver
  • created variable with "set"

What could be the issue?


Solution

  • The original code:

    location /foo-server/socket.io {
        proxy_pass ${FOO_SERVER_SOCKET_IO_URL}/socket.io;
        ...
    }
    

    Removed the /foo-server part of the URL before passing it upstream.

    The proxy_pass directive cannot perform that transformation when an Nginx variable is used.

    You can replicate that behaviour with a rewrite...break statement.

    For example:

    location /foo-server/socket.io {
        set $foo_server_socket_io ${FOO_SERVER_SOCKET_IO_URL};
        rewrite ^/foo-server(.*)$ $1 break;
        proxy_pass $foo_server_socket_io;
        ...
    }