0

I have a nodejs server that's served with nginx as reverse proxy. That part is ok, and static files locations are set up correctly. But I want the root address to serve a static html file, and I don't know how to configure nginx so that the root url is not redirectected to the node app. Here's my server block:

upstream promotionEngine {
 server 127.0.0.1:3001;
}

server {
    listen       3000;
    server_name  localhost;
    root C:/swaven/dev/b2b.pe/promotionEngine/templates/;
    index index.html;

    location / {
      proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_set_header X-NginX-Proxy true;
        proxy_pass http://promotionEngine;
        proxy_redirect off;
    }

    location /public/ {
      alias C:/swaven/dev/b2b.pe/promotionEngine/public/;
    }

    location /assets/ {
      alias C:/swaven/dev/b2b.pe/promotionEngine/assets/;
    }
}

htttp://localhost:3000/ping and http://localhost:3000/public/js/riot.js are correctly served.
But http://localhost:3000 keeps being sent to the node server, where I would like it to return a static index.html. If I remove the / location bloc, the html file is correctly served. How would I configure the location to work as reverse proxy for all urls except the root one ?

3 Answers 3

2

UPDATED: (based on comments and discussion)

You'll need 2 exact location blocks. One to intercept the / location and another to serve just /index.html.

An exact location block is described on nginx docs:

Also, using the “=” modifier it is possible to define an exact match of URI and location. If an exact match is found, the search terminates.

Simply using the index directive does not work. Because nginx creates an internal redirect to allow other blocks to match index.html. Which gets picked up by your proxy block.

upstream promotionEngine {
 server 127.0.0.1:3001;
}

server {
    listen       3000;
    server_name  localhost;

    # Do an exact match on / and rewrite to /index.html
    location = / {
      rewrite ^$ index.html;
    }

    # Do an exact match on index.html to serve just that file
    location = /index.html {
      root C:/swaven/dev/b2b.pe/promotionEngine/templates/;
    }

    # Everything else will be served here
    location / {
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header Host $http_host;
      proxy_set_header X-NginX-Proxy true;
      proxy_pass http://promotionEngine;
      proxy_redirect off;
    }

    location /public/ {
      alias C:/swaven/dev/b2b.pe/promotionEngine/public/;
    }

    location /assets/ {
      alias C:/swaven/dev/b2b.pe/promotionEngine/assets/;
    }
}
Sign up to request clarification or add additional context in comments.

5 Comments

I added the new location, but now I get a {"code":"ResourceNotFound","message":"/index.html does not exist"}. So the location is visited, but it still processes the \` location after that. Even with a break directive.
hmm is the alias path in the location = / block set to the directory which contains the index.html file?
oh, also you should be sending a request to localhost:3000, not localhost:3000/index.html that would match the second location block
Ah looks like this is the problem: nginx.org/en/docs/http/ngx_http_index_module.html If you read the bottom part, looks like index causes a redirect which then causes the second route to match...
1

You can use =/ this type of location have higher priority due to lookup:

location =/ {
  root ...
}

This request will not even try to reach other locations.

Comments

-1
Something like this, adjust for your own use case.

http {
    map $request_uri $requri {
        default          1;
        /                0;
    }
...........
    server {
        listen       80;
        server_name  www.mydomain.eu;
        root   '/webroot/www.mydomain.eu’;
        if ($requri) { return 301 https://www.mydomain.eu$request_uri; }
        location / {
            ..........
        }
    }

2 Comments

I don't know exactly why, but I understand if directives are bad: wiki.nginx.org/IfIsEvil
An IF should only be used to return a single state like shown above, IF is evil when used to continue config evaluation/operation. The above example is EXACTLY what an IF is meant to be used for and does not warrant by ANY example a -1. ea. [if (xx) { a; b; c; ... } is bad, only 'a' is ok]

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.