Node JS - Nginx - proxy_pass to a subdirectory - Koa - node.js

I'm running a Koa app on port 5000, and i'd like Ngnix to serve the app in a sub-directory - e.g: http://example.com/myNodeApp
Here's what I've currently got in /etc/nginx/sites-enabled/default
location ^~ /myNodeApp/ {
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://localhost:5000/;
}
This kind of works... apart from the fact that any redirect e.g this.redirect('/') in my Koa app goes to the the nginx web root /
Also, it doesn't render anything from my Koa apps' public directory e.g. stylesheets, javascript and images.
What am I doing wrong? Thanks.

I have recently come across the same problem and here's what I did to fix it.
In Server Config:
I had to add
rewrite ^/myNodeApp/(.*)$ /$1 break;
to the NGINX config, in the
location /myNodeApp/ {...}
block, under what you already have in your example.
In client side:
I added
<base href='/myNodeApp/'>
to the <head> of my html files (or pug layout file in my case). This prefixes any links with your subdirectory.
Note that you will need to remove any leading /'s from your existing links. Eg
<link rel="stylesheet" href="layout.css">
instead of
<link rel="stylesheet" href="/layout.css">
That one caught me out for a while.
Bonus:
If you're using Socket.IO, like I am, you'll need to make a few more changes to stop some errors appearing in your console. You need to pass it a path option and specify your subdirectory.
In your html files
var socket = io.connect("/", {path: "/myNodeApp/socket.io"})

Related

Express and Nginx figthing over routing

So i have a strange configuration that i need until i get to refactor a project later this year.
it is a static index.html landing page served with a location root "/" by NGINX.
i have a slash location like so:
location /channel/ {
proxy_pass http://node_server:5000/;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Ssl on;
proxy_cache_bypass $http_upgrade;
}
that express.js then handles. Express just serves a static folder with auto-generated content that a user can then navigate around in.
It works well in the sense that any appending slashes like:
/channel/open/
but ONLY if i have a trailing slash after "open". If i leave it out then NGINX will throw a "404 Not Found", if i keep it in, it works as intended.
The thing is that a user should be able to click on a folder in the static served directory to traverse a file structure, and the way that works in a browser is that it does not append a trailing slash to a directory name when clicked, so NGINX then throws the "404".I have tried a NPM package called 'express-slash' but that did not solve the issue.
i was hoping someone here had some suggestions on what i could try out next?
Details about trailing slash behavior can be found here: https://serverfault.com/questions/607615/using-trailing-slashes-in-nginx-configuration
But if your goal is to configure NGINX to allow directory traversal, you may be looking for the autoindex directive: http://nginx.org/en/docs/http/ngx_http_autoindex_module.html

NGINX + ExpressJS - Reverse proxy for URLs in HTML

I have a NodeJS + ExpressJS app running on port 3000 which has a route:
router.get('/getHello', function(req, res) {
res.send('Hello, world!');
});
and a HTML page which does a GET on this route
<a href="/getHello">
<input type="button" value="Visit Helo World page" />
</a>
This standalone app works as intended. It displays Hello, world! when the button is pressed.
Now, here's the problem:
I have setup a reverse proxy on this app using nginx. Here's the config file from sites-available (linked with sites-enabled)
server {
listen 80;
server_name localhost;
location /routetest/ {
proxy_pass http://127.0.0.1:3000/;
proxy_http_version 1.1;
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_set_header Host $host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header X-Forwarded-Proto $scheme;
proxy_redirect off;
proxy_cache_bypass $http_upgrade;
}
}
The app opens fine when I visit http://localhost/routetest but when I click on the button, it opens http://localhost/getHello whereas I wanted it to open http://localhost/routetest/getHello. Since http://localhost/getHello is not defined, I end up with a 404. (On the other hand, http://localhost/routetest/getHello correctly returns the Hello, world message)
Now, my question is:
My frontend is written with / as the base path (to make all GET and POST requests), for example <a href="/getHello"> and I feel manually appending /routetest/ before all URLs in my HTML not a good practice (since I may want to change this base path later and then I'll have to update it everywhere). So, is there a way for NGINX or some express middleware to add /routetest/ for URLs that are written with / as the base path, without having to change it in my HTML manually?
By a long way the easiest solution is to use relative paths without the leading / if that's an option that's available to you.
Rewriting URLs in the response is somewhere between tricky and impossible in the general case. If you think you can successfully identify the relevant URLs in your content you might be able to use nginx's catchily titled ngx_http_sub_module:
http://nginx.org/en/docs/http/ngx_http_sub_module.html
There are various Express middleware implementations that do a similar thing but I couldn't find one that looked reliable enough to recommend. The basic approach would be similar to the compression middleware if you fancy giving it a go yourself. Again it's quite difficult in general but depending on the specifics of how you serve up your HTML it might not be too bad.

nginx link nodejs app to subdomain

I have a dropplet on digital-ocean where I have a node.js app and nginx.
So, I installed nginx and then in /etc/nginx/sites-available/ I created a new file called api where I have the following content:
server {
server_name api.my-website.com;
location / {
proxy_set_header X-Real_IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $proxy_host;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://127.0.0.1:9000; // this is where the node app lives
}
}
After I create that I restared nginx but if I go to api.my-website.com I dont see anything (my api has a landing page on /), but if I go to my-website.com:9000 I see the landing that should be on api.my-website.com.
Can someone explain me please what I'm doing wrong?
You did not included your /etc/nginx/sites-available/api file into /etc/nginx/nginx.conf. You need to include /etc/nginx/sites-available/api in /etc/nginx/nginx.conf inside http module and then restart or reload nginx. Your /etc/nginx/nginx.conf may looks like
http {
# other lines for logging, gzip, etc.
# other include may here
# Your include as following
include /etc/nginx/sites-available/api;
}

NGINX proxy and NodeJS App : href and sytylesheets and javascripts

I have a node app the has a stylesheet,javascript and images directories in a public directory from the main node app directory.
When the index.html is rendered the HTML href calls to these directories fails, the proxy does not know how to route them since the location is not provided in the href .
So im stumped as to whether this is a Nginx or Node issue. I can proxy to other webservers such as Tomcat that do not have this issue.
Rendered HTML:
<link rel='stylesheet' href='/stylesheets/foundation.min.css' />
<link rel='stylesheet' href='/stylesheets/motion-ui.css' />
<link rel='stylesheet' href='/stylesheets/foundation-icons/foundation-icons.css' />
<link rel='stylesheet' href='/stylesheets/js-image-slider.css' />
<link rel='stylesheet' href='/stylesheets/generic.css' />
<link rel='stylesheet' href='/stylesheets/style.css' />
<script src="/javascripts/js-image-slider.js"></script>
<script src="/javascripts/vendor/modernizr.js"></script>
NGINX: location
I have tried many variations on this based on blogs but find none that work.
location / {
root html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
#Node App Server : latest try
location ~ /internship {
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://127.0.0.1:3000;
}
#Tomcat server
location /bi {
rewrite ^/bi(.*) /$1 break;
proxy_pass http://127.0.0.1:5566;
proxy_set_header Host $host;
}
It seems it might be a good idea for you to read into Nginx a bit more.
As for your problem it seems you don't have anything that handles sending any files back as a response.
Looking at Nginx docs shows the following example for returning images:
location /images/ {
try_files $uri /images/default.gif;
}
This example looks for the location prefix of /images/ and then it'll try to find the requested location else return a default image.
You could make a similar request with your stylesheets and js.
Take a look at the try_files documentation here.
However, I would spend a bit more time exploring what these directives mean because you can easily open a security hole by not denying access to other parts of your website.

varnish, nginx, & node.js: static nginx html pages with node.js fallback

am running varnish on EC2 in front of nginx which routes to node.js.
What I would like is to serve specific static HTML pages from certain routes (like, / for index.html) via nginx, but have all other routes be handled by node.js.
As an example, / would be sent by nginx in the form of a static HTML page, while anything not matching, say /dynamic_stuff or /dynamic_stuff2, would be processed by node.js.
In other threads online, other people were putting node.js in a separate dir entirely, like /node/dynamic_stuff but I didn't want to have a separate dir for my routing.
Right now I have / served up by node.js like everything else but if I'm just testing my node.js server and I take it down, I'd like / to fallback to an nginx version of index.html. In this case, if my node.js server is taken down, then I get a 502 Bad Gateway.
I'm not too worried about performance from serving up files via nginx vs. node.js, I just figure that I want to have nginx handling basic pages if node.js goes down for whatever reason.
Relevant script:
location = / {
index index.html
root /path/to/public
try_files $uri $uri/ 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 node_js;
}
If I use this above code, all requests still get sent to node.js, including /.
I think the simplest thing to do if it's just the index.html is to set index to
index index.html
root /path/to/public
All files in your public directory should now be served from nginx.
Now put this index.html in the public directory of your node app. The rest will be proxied from nginx to the node instance.
Of course you can simply put other static html in subdirectories if you want:
public/about(index.html
public/faq/index.html
...

Resources