Search code examples
nginxnginx-locationnginx-config

nginx location matches multiple times


My nginx.conf looks something like this

server {
  listen 443 ssl;
  server_name test.com;
  client_max_body_size 100M;

  # test.com/ should be a static page
  location = / {
    root /var/www/
    try_files $uri $uri/ /index.html;
    break;
  }

  # everything else should go to the upstream app server
  location / {
    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 $host;
    proxy_http_version 1.1;
    proxy_pass http://127.0.0.1:3000;
  }
}

My issue is that when I visit test.com nginx seems to evaluate the location / block as well because it's proxying the request to my upstream server rather than stopping at the location = / block. I've tried including break; in the location = / block and that didn't change the behavior at all. I know it's matching the first location = / block because the request that I see on my app server is for /index.html which is presumably rewritten by the try_file directive (if I change that to /foo.html instead, I see it reflected on my app server).

I've tried nginx location testing tools like https://nginx.viraptor.info and that said the final match should only be the "exact match" described by the location = / block.

And yes, I've restarted nginx after every time I changed config file.

Anyone have any clue why this is happening? Any help would be appreciated!


Solution

  • Nginx processes two URIs, first the / and then the internally rewritten /index.html. Your configuration processes the second URI in the location / block.

    Either, add an exact match location for the second URI, for example:

    root /var/www;
    location = / { ... }
    location = /index.html { }
    location / { ... }
    

    Or, you can arrange for try_files to process the URI within the same location:

    root /var/www;
    location = / { 
        try_files /index.html =404;
    }
    location / { ... }
    

    See this document for details.