NGINX proxy and NodeJS App : href and sytylesheets and javascripts - node.js

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.

Related

index.html is loaded but css and js urls not found (404) / working great locally

I am stuck with a path problem I cannot solve even after I had spent 3 hours searching on Stack Overflow and google, trying everything with no success. I am sorry if I walked nearby the solution elsewhere without seeing it, please notice that I really tried.
So, my project is a backend Node JS, front React on an ubuntu 22.04 Nginx server (digital ocean).
My server is really simple :
// main.js
const Port_TCP = 3005;
const express = require('express');
const path = require("path");
let app = express();
app.use(express.json());
app.use(express.static(__dirname + '/public'));
app.set('port', Port_TCP);
app.get("*", function(req, res) {
res.sendFile(path.join(__dirname, '/public/index.html'))
})
app.listen(Port_TCP);
And the public/index.html file :
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>My website</title>
<link href="css/app.css" rel="stylesheet">
<link rel="icon" type="image/x-icon" href="imgs/ico.png">
</head>
<body>
<!-- React root DOM -->
<div id="MainRouter"></div>
<!-- React JS -->
<script type="application/javascript" src="js/app.js" defer></script>
</body>
</html>
Problem is this :
On my localhost (windows), I have no problem, website is running as it should.
On my server (ubuntu), the website is reached, the index.html is loaded, but every url inside it are wrong and throw me classic 404 errors :
GET https://my-website.com/css/app.css net::ERR_ABORTED 404 (Not
Found)
GET https://my-website.com/js/app.js net::ERR_ABORTED 404 (Not Found)
(tab icon is not found either)
edit - strange thing, on the server I can delete the app.get("*"...) part and I still reach the page. If I do that on localhost, got a 502...
My project folders and file set up is this :
/main.js (server)
/mix-manifest.json
/package.json
/package-lock.json
watcher.js (for nodemon)
webpack.mix.js
/js and /sass folder (which contain react project)
/public/
/public/index.html
/public/css/app.css
/public/js/app.js
/public/imgs/
edit - My NGinx configuration in etc/sites-available is :
server {
root /var/www/mywebsite.fr/public;
index index.html index.htm index.nginx-debian.html;
server_name mywebsite.fr www.mywebsite.fr;
location / {
proxy_pass http://localhost:3005;
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;
try_files $uri $uri/ =404;
}
listen [::]:443 ssl; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/mywebsite.fr/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/mywebsite.fr/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
if ($host = www.mywebsite.fr) {
return 301 https://$host$request_uri;
} # managed by Certbot
if ($host = mywebsite.fr) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
listen [::]:80;
server_name mywebsite.fr www.mywebsite.fr;
return 404; # managed by Certbot
}
If you can give me a lead it would be amazing.
It's because of relative path is not correct.
In develop and build may a bit different of relative path.
In reactjs directory, file package.json
modify or add homepage it could be help:
"homepage": "file:///android_asset/", (for android)
"homepage": ".", (for android and windows, iOS not tested)
if above not working change homepage value to your public folder path

nginx returning 405 method not allowed for node apis with localized angular folders

I did changes in ngnix file to make it work for localized angular dist folder with multiple languages. client side application working properly with url routing etc but node apis for authentication are returning "405 method not allowed" error. any help would be appreciated.
Solutions I have tried,
error_page 405 =200 $uri; -- it gives 200 in status code with empty response
tried setting up orgin * but still it did not working
Below is my nginx configuration
root /var/www/web/dist;
# Fallback to default language if no preference defined by browser
if ($accept_language ~ "^$") {
set $accept_language "da";
}
# Redirect "/" to Angular application in the preferred language of the browser
rewrite ^/$ /$accept_language permanent;
# Everything under the Angular application is always redirected to Angular in the
# correct language
location ~ ^/(da|en) {
try_files $uri /$1/index.html?$args;
}
location /nodeApi/ {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header content-type "application/json";
proxy_cache_bypass $http_upgrade;
proxy_pass http://localhost:4444/nodeApi;
}

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.

Error in initializing an app in express.js

I have created a testApp using express.js in a server containing nodeJS environment. Site is running in the http://localhost:3000 And i have checked the output via command line -
curl http://localhost:3000/
Output-
<!DOCTYPE html>
<html>
<head>
<title>Express</title>
<link rel="stylesheet" href="/stylesheets/style.css">
</head>
<body>
<h1>Express</h1>
<p>Welcome to Express</p>
</body>
</html>
But i couldn't find it in my domain. It is showing an error like this -
Not Found
404
Error: Not Found
at /home/user/testApp/app.js:30:13
at Layer.handle [as handle_request] (/home/user/testApp/node_modules/express/lib/router/layer.js:95:5)
at trim_prefix (/home/user/testApp/node_modules/express/lib/router/index.js:312:13)
at /home/user/testApp/node_modules/express/lib/router/index.js:280:7
at Function.process_params (/home/user/testApp/node_modules/express/lib/router/index.js:330:12)
at next (/home/user/testApp/node_modules/express/lib/router/index.js:271:10)
at /home/user/testApp/node_modules/express/lib/router/index.js:618:15
at next (/home/user/testApp/node_modules/express/lib/router/index.js:256:14)
at Function.handle (/home/user/testApp/node_modules/express/lib/router/index.js:176:3)
at router (/home/user/testApp/node_modules/express/lib/router/index.js:46:12)
What could be the possible reason for such kind of error ?
EDIT:
App Structure:
.
app.js
bin
www
package.json
public
images
javascripts
stylesheets
style.css
routes
index.js
users.js
views
error.jade
index.jade
layout.jade
Ngynx configuration file:
server {
listen 80;
server_name 10.10.10.15;
location / {
proxy_pass http://localhost:8080;
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 /testApp {
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;
}
}

Node JS - Nginx - proxy_pass to a subdirectory - Koa

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"})

Resources