How to make Nginx redirect a request to only one location?

January 4, 2019 620 views
Nginx Ubuntu 18.04

I have a reverse proxy for two locations / and /services

server {
…

    location / {
        proxy_pass http://localhost:3000;
        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;
    }

    location /services {
        proxy_pass http://localhost:3001;
        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;
    }

…
}

And there are two NodeJS APIs one is listening on port 3000 and the other on 3001. Whenever I send a request to example.com/services it gets handled by both apps. I want it to get handled only by the second app listening on port 3001. How do I achieve that?

1 Answer

This article explains location matching well:

https://www.digitalocean.com/community/tutorials/understanding-nginx-server-and-location-block-selection-algorithms

But “location /” will always be matched first because /services isn’t an actual file on the server.

Cheers

by Justin Ellingwood
Nginx is one of the most popular web servers in the world. In this guide, we will discuss how Nginx selects the server and location block that will handle a given client's request. We will go over the algorithm in place, as well as the directives and options you can use to modify the selection process.
  • I’m still not sure what is the right way to achieve that, any ideas?

    • Can you post the full contents of the server block including the config that was snipped?

      Cheers

      • 
        server {
            server_name example.com www.example.com;
        
            location / {
                proxy_pass http://localhost:3000;
                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;
            }
        
            location /services {
                proxy_pass http://localhost:3001;
                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;
            }
        
            listen [::]:443 ssl ipv6only=on; # managed by Certbot
            listen 443 ssl; # managed by Certbot
            ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # managed $
            ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # manage$
            include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
        }
        
        server {
            if ($host = www.example.com) {
                return 301 https://$host$request_uri;
            } # managed by Certbot
        
        
            if ($host = example.com) {
                return 301 https://$host$request_uri;
            } 
            # managed by Certbot
            listen 80;
            listen [::]:80;
            server_name example.com www.example.com;
            return 404; # managed by Certbot
        }
        
Have another answer? Share your knowledge.