nginx loopback reverse proxy can't access custom paths - angularjs

Im running this loopback app in my server and trying to access it through an nginx reverse proxy, but can't seem to get nginx configured correctly, I'm a total noob to nginx. Here's my config file /etc/nginx/sites-available/example.com
server {
listen 80;
server_name www.example.com;
server_name example.com;
server_name _;
root /apps/example/client;
location ~ ^/.well-known {
allow all;
}
location / {
return 301 https://example.com;
}
}
server {
server_name example.com;
server_name www.example.com;
#listen 80;
# SSL configuration
listen 443 ssl ;
ssl_certificate /etc/letsencrypt/live/www.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/www.example.com/privkey.pem;
root /apps/example/client;
# Check Alive
location ~ ^/.well-known {
allow all;
}
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $http_host;
proxy_bind 127.0.0.1;
proxy_pass http://127.0.0.1:3000/;
}
location /api {
proxy_pass http://127.0.0.1:3000/api;
}
location /explorer {
proxy_pass http://127.0.0.1:3000/explorer;
}
}
and my loopback server serves static files like this:
app.use(loopback.static(path.resolve(__dirname, '../client')));
and at the end of my server.js file I serve the index.html file for any path not processed so angular processes that path in the front end
function startsWith(string, array) {
for(let i = 0; i < array.length; i++)
if(string.startsWith(array[i]))
return true;
return false;
}
let ignoredPaths = ['/css', '/fonts', '/img', '/js', '/lib', '/sfx', '/views', '/api'];
app.all('/*', function(req, res, next) {
//Redirecting to index only the requests that do not start with ignored paths
console.log("Requested url: ",req.url);
if(!startsWith(req.url, ignoredPaths)) {
res.sendFile('index.html', {root: path.resolve(__dirname, '../', 'client')});
} else {
next();
}
});
The issue is that I can only access http://www.example.com/ and it takes a lot to load and the url flashes many times like it's redirecting a lot of times, I redirect in front-end with angular to /home, I have the angular routing to use html5 to remove the /#!/ from the path, but I always get a Bad Gateway error if I try to access any other path, say http://www.example.com/admin/login and it's a nginx error, it's not reaching loopback so it can serve the index file. I've tried the try_files $uri $uri/ /index.html; but if I try to access any other custom path, say /auth/facebook it forces it to load it through index.html and that's a custom path I have setup on loopback to do special behaviour. I have no idea how to solve this, I just used that template config file, all I need is for it to redirect all requests from example.com to my app in localhost:3000 and do the same in the opposite direction.

So i kept trying, and tried again using the try_files with a #path (I guess that's kind of a label or something) and what I was missing when I tried it before was to attach $uri at the end of the proxy_pass
It ended up like this:
location / {
try_files $uri $uri/ #proxy;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $http_host;
proxy_bind 127.0.0.1;
proxy_pass http://127.0.0.1:3000/;
}
location #proxy {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $http_host;
proxy_bind 127.0.0.1;
proxy_pass http://127.0.0.1:3000$uri;
}
And all works dandy now :P.

Related

How to configure nginx for 2 react + express app

i've been struggling to configure the sites-available config file and was hoping to get some guidance. I'm trying to point sub.domain.com/app1 and sub.domain.com/app2 to the correct location. I have 2 react and express running on port 2000 and port 3000, and they are both working file when accessing the ip address and port number (xx.xx.xx.x:2000). One of the app works if the location is root(/), but as soon as I try to change the location or add another the page turns blank. Any help would be appreciated.
server {
listen 80;
server_name sub.domain.com;
location /app1 {
proxy_pass http://localhost:2000;
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;
proxy_buffering off;
proxy_request_buffering off;
proxy_cache_revalidate on;
}
location /app2 {
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;
proxy_buffering off;
proxy_request_buffering off;
proxy_cache_revalidate on;
}
}
If you have a standard react application(not a next.js one) then you will need to first build it and then you have to place it in the correct path, as example /var/www/html/app1/
So your default.conf would include the following:
location /app1 {
alias /var/www/html/app1/;
try_files $uri /index.html =404;
}
location /app2 {
alias /var/www/html/app2/;
try_files $uri $uri/ index.html =404;
}
Now, if you run CRA then you should have a look on their deployment guide, especially in Serving the Same Build from Different Paths

How to host an MS Teams app in a container with an nginx proxy pass

I have to host my teams app under https://mysite/myapp
The host is ruled by nginx like that
location /myapp {
proxy_pass http://ip:port;
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-Forwarded-Proto $scheme;
proxy_http_version 1.1;
proxy_set_header Connection "";
}
http://ip:port is the real host of the teams app inside a docker container.
This is the nginx config for the container
server {
listen 80;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
this is the docker file (a part of it)
FROM nginx:alpine
COPY --from=build /nginx/nginx.conf /etc/nginx/conf.d/default.conf
COPY --from=build /build /usr/share/nginx/html
If I try http://ip:port/tab I see
If I try https://mysite/myapp/tab I can't see any message from the page and the browser seems to load the index.html page
Is there a way to make the react routing work with this settings?

Nginx Resource not found on refresh with React router

I am running a React app on Nginx in production.
If I refresh on any route different that "/" I get "Resource not found".
for example:
Refresh on http://www.aaaa.com will be OK
Refresh on http://www.aaaa.com/bbb/ddd will result in Resource not found.
I searched a lot and tried everything I found including adding try_files $uri $uri/ /index.html;
This is part of my conf file:
upstream ggg_stream {
server ggg.aaa.com:9090 fail_timeout=0;
}
server {
listen 80;
server_name aaa.com;
root /var/www;
location / {
try_files $uri $uri/ /index.html;
}
location /ggg {
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-Forwarded-Proto $scheme;
# Fix the "It appears that your reverse proxy set up is broken" error.
proxy_pass http://ggg_stream/;
proxy_read_timeout 90;
# proxy_redirect http://127.0.0.1:8080 http://34.248.183.236:8080;
# Required for new HTTP-based CLI
proxy_http_version 1.1;
proxy_request_buffering off;
}
}
This server also used as a proxy so it has many stream mappings such as ggg
The site content is located at /var/www
We use React router 4.
Any ideas?
Regards,
Ido

Express API backend receiving requests but not responding, Nginx

I have a front end reactjs being served by nginx. shown here:
server {
listen 80 default_server;
server_name website.* www.website.*;
root /home/developer/website/frontend/build;
location / {
try_files $uri /index.html;
}
location /api {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://127.0.0.1:4000;
}
}
Additionally, I have a second express app receiving requests at 127.0.0.1:4000. The front end calls fetch to 'api/something' and the express app receives that and handles it but does not respond, the client side errors with 504 (Gateway Time-out). Any ideas?
You are missing the upstream server directive. Try this
upstream api {
server 127.0.0.1:4000;
}
# remove www from the url
server {
listen 80;
server_name www.website.com;
return 301 $scheme://website.com$request_uri;
}
server {
listen 0.0.0.0:80;
server_name website.com website;
error_log /var/log/nginx/website.com-error.log error;
access_log /var/log/nginx/website.log;
# pass the request to the node.js server with the correct headers
location /api/ {
proxy_pass http://api/;
proxy_ignore_headers X-Accel-Expires Expires Cache-Control;
proxy_ignore_headers Set-Cookie;
proxy_hide_header Set-Cookie;
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_redirect off;
proxy_set_header X-NginX-Proxy true;
}
}

How to handle redirects in Express application with Reverse Proxy

I have two Express powered NodeJS applications that are being served by Nginx. One application is a RESTful API, that is consumed by an Angular SPA and the other one is an Admin portal. This is something I'm trying to achieve here:
location / {
# Serves Client Side Angular Application
}
location /api {
# Serves RESTful Application
}
location /admin {
# Serves Admin Portal
}
Here is my complete configuration for nginx:
server {
server_name localhost;
listen 80;
listen [::]:80;
index index.html;
location / {
expires -1;
add_header Pragma "no-cache";
add_header Cache-Control "no-store, no-cache, must-revalidate, post-check=0, pre-check=0";
root /var/www/example/client/dist;
try_files $uri $uri/ /index.html =404;
}
location /admin/ {
proxy_pass http://127.0.0.1:3010/;
proxy_http_version 1.1;
rewrite /admin/(.*) /$1 break;
proxy_redirect off;
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/admin/;
proxy_set_header X-NginX-Proxy true;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
location /api {
proxy_pass http://127.0.0.1:3011;
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 Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
Both of the NodeJS application utilizes forever and run on their defined ports, perfectly.
The problem I'm facing with my admin application, when I try to hit http://example.com/admin it redirects me to http://example.com/login when it should redirect me to http://example.com/admin/login. I tried to solve this issue by adding a middleware to the admin application, like:
app.use('*', function (req, res, next) {
if(process.env.target === 'dev'){
if(req.originalUrl.indexOf('/admin') > -1){
res.redirect('/admin' + req.url);
}
next();
}
});
But this doesn't work. How should I handle this situation? Is there anyway nginx can handle application redirects? If not, how should I handle it in application for different environments(Dev, Staging, Prod etc)? I'm using nginx 1.4.6, node 0.12.2 and express 4.12.2. I have no issue if I have to add any 3rd party module in my application but I'd prefer if there is an nginx solution for my problem.
Thanks.
The problem with your nginx config is the rewrite for the /admin route:
rewrite /admin/(.*) /$1 break;
With this rule in place your admin portal node app doesn't know that its paths are all hosted off of a /admin root, so if your app does a redirect relative what it thinks is root, eg res.redirect('/login'), it makes sense that it would send the browser to localhost/login.
An alternative would be to remove your nginx rewrite and just make the admin portal aware of this /admin path. That way you have the option of redirecting to a relative path, like this: res.redirect('login') which tells express to take the current request's path into account. You can use the express.Router to make this cleaner, like this for example:
var adminRoutes = express.Router()
.get('/', function(req, res) {
if(!req.user) {
// Will redirect to /admin/login
res.redirect('login');
} else {
res.send('Hello');
}
})
.get('/login', login);
// Tell express to host all routes above under a common /admin root
app.use('/admin', adminRoutes);
If on the other hand there's a better reason why you must have the nginx rewrite, you can always just include the /admin root manually for all of your app's redirects. You could provisionally append this mount path by reading it from a custom header set byproxy_set_header. For example:
app.use(function(req, res, next) {
res.mountedAt = req.headers['X-Mounted-At'];
next();
});
app.get('/', function(req, res) {
res.redirect(path.join(res.mountedAt, '/login'));
});
I solved this by combining Andrew Lavers's first solution with
location /admin/ {
proxy_pass https://127.0.0.1:3010/admin/;
}

Resources