Nginx Reverse Proxying to Node.js with Rewrite
I have made nginx serve static files without even passing those requests to node by adding location directive to the app's nginx configuration file (which is included in nginx.conf):
location ~ /(img|js)/ {
rewrite ^(.*)$ /public/$1 break;
}
location / {
proxy_pass http://localhost:3000/;
...
}
In case request comes to /img or /js directory nginx serves files from /public/img or /public/js directory respectively. All other requests are proxied to node.
You can add more directories if you need (like /css or /views, if you store templates there that you want to use both in node and in browser) and have any directory structure inside those directories, nginx just prepends /public to them and gets files from there without your node app even knowing about it.
Related videos on Youtube
Maros
Updated on June 20, 2022Comments
-
Maros almost 2 years
I have several apps running behind an Nginx reverse proxy, one of which is a Node server with Express.js. I'm proxying
domain.com/demo/app/<path>
tolocalhost:7003/<path>
using this Nginx config:http { ... server { listen 80; server_name domain.com; ... location /demo/app { 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_set_header X-Scheme $scheme; rewrite ^/demo/app/?(.*) /$1 break; proxy_pass http://localhost:7003; } ... } }
This works great and
app
receives requests as if it was rooted at/
. The problem isapp
handles its own static files and might make requests for routes such ascss/app.css
orimages/image.jpg
. But because of the reverse proxy, these actually exist at/demo/app/css/app.css
and/demo/app/images/image.jpg
respectively.I've solved this by getting Nginx to pass to Node a custom header indicating the root path, which the Node server prepends to the URLs of all subsequent requests. But now my code is littered with these root path strings. For example, part of my back-end templates:
link(rel='stylesheet', href="#{basePath}/css/base.css") link(rel='stylesheet', href="#{basePath}/css/skeleton.css") link(rel='stylesheet', href="#{basePath}/css/layout.css")
What's a more elegant way to handle this? Isn't there a way to get Nginx to recognize requests coming from an upstream server and automatically forward them to that server?
-
Maros over 11 yearsHow do you handle AJAX requests? I'd like to not have to prepend AJAX URLs in the JavaScript with
/demo/app
-
esp over 11 yearsWith the configuration above all requests (other than to /img/... and /js/...) will be proxied to node.js assuming it listens to the port 3000.
location /
matches all requests that were not matched by the previous location directive. -
esp over 11 yearsIf you need to make your app process requests as if they come to
/
you still can rewrite requests the way you did... I would prefer to have this routing inside an application but it is my personal preference... I am not sure I understood correctly what you want to achieve, but the only way not to include {basepath} in links is to rewrite requests the way I did. It also allows not to process static files in node, but if you want to, you still can proxy them too...