Nginx multiple locations for multiple Node JS Express Apps

Nginx multiple locations for multiple Node JS Express Apps



I have the following configuration:


location /
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://localhost:3000; # this is where our node js app runs at
proxy_set_header Host $http_host;
proxy_cache_bypass $http_upgrade;
proxy_redirect off;



Which proxies [SERVER_IP]/ to localhost:3000 so that it basically routes everything to the node js app.


[SERVER_IP]/


localhost:3000



I then went ahead and wrote another nodejs app, which runs on port 5000, instead of 3000:


5000


3000


location /
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://localhost:3000; # this is where our node js app runs at
proxy_set_header Host $http_host;
proxy_cache_bypass $http_upgrade;
proxy_redirect off;


location /testing
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://localhost:5000; # this is where our node js app runs at
proxy_set_header Host $http_host;
proxy_cache_bypass $http_upgrade;
proxy_redirect off;



However if I go to [SERVER_IP]/testing it routes it as /testing to my first app which then generates the Express JS message: "Cannot GET /testing".


[SERVER_IP]/testing



I changed the order, restarted nginx without problems. Any idea why it would not work? I assume nginx is the first instance before it gets routed to Node JS.
If I change the port of the location / ... I can get the second app, but I would want to run them parallel to each other.


location / ...



Thanks




3 Answers
3



Since server_ip/testing does match the / location block, you will always go inside that location block. At this point NGINX doesn't go to the next block as it has already found the block that matches the request.


server_ip/testing


/



You should move the second location block to the top and use = instead, like this


=



location = /testing


location = /testing



to forward the request to nodeApp2:5000


nodeApp2:5000



Read the NGINX documentation here to understand how NGINX location blocks work along with regex rules.





I just tried that and it somehow still is choosing the / block
– Janosch Hübner
Aug 25 at 15:53





Just for testing sake, could you change it to location ~ "testing" instead? and still, keep this as the first location block?
– lakshman.pasala
Aug 25 at 15:57



location ~ "testing"





Actually, the method before worked as well! However now /testing is forwarding it to nodeApp2:5000/testing and not nodeApp2:5000/
– Janosch Hübner
Aug 25 at 16:11





Yeah, this was just for testing. You should use the previous method instead.
– lakshman.pasala
Aug 25 at 16:31





No, even the location = /testing is forwarding to :5000/testing
– Janosch Hübner
Aug 25 at 16:34



In your default file, only change the port number in your proxy_pass, and leave location as /



Example of how your default would look:


server
listen 80 default_server;
listen [::]:80 default_server;
root /root/port-two/build;
server_name www.myfirstsite.com myfirstsite.com;
location /
proxy_pass http://127.0.0.1:8001;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_max_temp_file_size 0;
client_max_body_size 10m;
client_body_buffer_size 128k;
proxy_connect_timeout 90;
proxy_send_timeout 90;
proxy_read_timeout 90;
proxy_buffer_size 4k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;


server
listen 80;
listen [::]:80;
server_name www.mysecondsite.com mysecondsite.com;
location /
proxy_pass http://127.0.0.1:8002;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_max_temp_file_size 0;
client_max_body_size 10m;
client_body_buffer_size 128k;
proxy_connect_timeout 90;
proxy_send_timeout 90;
proxy_read_timeout 90;
proxy_buffer_size 4k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;




And make sure the .env file of each app has a PORT variable corresponding to the number you gave it on the default file.



.env for myfirstsite.com


PORT=8001



.env for mysecondsite.com


PORT=8002



You'll probably find it's actually your second app which is generating the Express JS message: "Cannot GET /testing".



Nginx proxy_pass directives behave differently based upon what can appear to be very minor differences in how you define them. If you specify a location block and proxy_pass it to a server with no path defined then the entire client request uri will be passed to the upstream server.



http://localhost/testing will proxy to http://localhost:5000/testing



However, if you specify a proxy_pass directive with anything appended, Nginx will replace the part of the client request which matches the location block with the path you appended to your proxy_pass directive.



So this, with just an extra slash at the end:


location /testing/ {
proxy_pass http://localhost:5000/;



Now results in Nginx doing this:



http://localhost/testing -> http://localhost:5000/



And this:


location /testing/ {
proxy_pass http://localhost:5000/foo/;



Would do this:



http://localhost/testing/bar/ -> http://localhost:5000/foo/bar/



In summary, proxy_pass to a naked server:ip to pass entire client request uri, add a single slash to remove part of the uri, or add something else to substitute.



The other answer suggesting it's caused by the order of your location blocks is incorrect, with all due respect to the person who answered I would recommend you read the information from the link they posted but not follow their advice, as they appear slightly confused about the way Nginx selects location blocks themselves.






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

𛂒𛀶,𛀽𛀑𛂀𛃧𛂓𛀙𛃆𛃑𛃷𛂟𛁡𛀢𛀟𛁤𛂽𛁕𛁪𛂟𛂯,𛁞𛂧𛀴𛁄𛁠𛁼𛂿𛀤 𛂘,𛁺𛂾𛃭𛃭𛃵𛀺,𛂣𛃍𛂖𛃶 𛀸𛃀𛂖𛁶𛁏𛁚 𛂢𛂞 𛁰𛂆𛀔,𛁸𛀽𛁓𛃋𛂇𛃧𛀧𛃣𛂐𛃇,𛂂𛃻𛃲𛁬𛃞𛀧𛃃𛀅 𛂭𛁠𛁡𛃇𛀷𛃓𛁥,𛁙𛁘𛁞𛃸𛁸𛃣𛁜,𛂛,𛃿,𛁯𛂘𛂌𛃛𛁱𛃌𛂈𛂇 𛁊𛃲,𛀕𛃴𛀜 𛀶𛂆𛀶𛃟𛂉𛀣,𛂐𛁞𛁾 𛁷𛂑𛁳𛂯𛀬𛃅,𛃶𛁼

Edmonton

Crossroads (UK TV series)