I've been develop an API with Express and Node.js. I have a simple routes and need to setup Nginx as a reverse proxy (following this steps: https://www.digitalocean.com/community/tutorials/how-to-set-up-a-node-js-application-for-production-on-ubuntu-16-04#set-up-nginx-as-a-reverse-proxy-server) but when I create a GET request my browser says: "Cannot GET /video/GetVideo/some_id".
Node code:
_apiRoutes = express.Router();
_apiRoutes.get('/video/GetVideo/:VideoID', (req, res) => {
getVideo(req.params, (result) => {
res.json(result);
});
});
_apiRoutes.get('*', function (req, res) {
res.status(404).send('yay!, are you lost?');
});
app.use('/api', _apiRoutes);
last code generate a route like: http://some_url/api/video/GetVideo/:VideoID
Nginx code:
...
location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
#try_files $uri $uri/ =404;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header x-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://localhost:3500;
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;
Related
When I run my application on chrome, I get the error. Websocket doesn't work, but it works locally.
this is my nginx server setup. I have 2 server instances. I don't know if that is the problem. Anyone knows the best way to fix this??
server {
listen 80;
server_name mydomain + .com;
rewrite ^/(.*) https://mydomain + .com/$1 permanent;
}
server {
listen 443 ssl;
listen [::]:443 ssl;
root /var/www/html;
index index.html index.htm index.nginx-debian.html;
server_name mydomain + .com;
ssl_certificate /home/chained.crt;
ssl_certificate_key /home/mykey.key;
// Frontend Setup
location / {
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;
}
// API SETUP
location /api {
proxy_pass http://localhost:8000;
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;
}
// SOCKET.IO SETUP
location /socket.io/ {
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 false;
proxy_pass http://localhost:8000;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
this is my nodejs setup for backend.
const app = express()
const httpServer = https.createServer({}, app)
const io = require('socket.io')(httpServer, {
cors: {
origin: '*',
methods: ['GET, POST'],
credentials: true,
allowedHeaders: ['custom-header'],
},
})
httpServer.listen(port, () => {
console.log(`Server running on port ${port}`)
})
MY react setup looks like this
useEffect(() => {
if (!socket.current) {
socket.current = io(process.env.REACT_APP_API_APP)
console.log('SOCKET', socket.current)
}
if (socket.current) {
socket.current.emit('join', { userId: user._id })
socket.current.on('connectedUsers', ({ users }) => {
users.length > 0 &&
dispatch({
type: 'SET_CONNECTED_USERS',
payload: users,
})
// users.length > 0 && setConnectedUsers(users)
})
}
My application works locally. but on nginx, It doesn't work. I just get the error as shown in the image.
I am new to servers. Any help would be appreciated.
I am working on an application, I used nodejs express as the server and reactjs for the client.
Here's my config for the server for socketIO
const server = app.listen(port, () =>
console.log(`Server running on port ${port}`)
) // Port is 8000
const io = require('socket.io')(server, {
cors: {
origin: '*',
},
})
For the react app, I called
useEffect(() => {
if (!socket.current) {
socket.current = io(process.env.REACT_APP_API)
} // REACT_APP_API is http://localhost:8000
}
This works very well for my localhost.
When I run this on nginx, I get WebSocket connection to 'wss://mydomain.com:
I configured my nginx as this
location / {
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;
}
location /api {
proxy_pass http://localhost:8000;
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 /socket.io/ {
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 false;
proxy_pass http://localhost:3000/socket.io/;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
In my .env in nginx, i have set my REACT_APP_API to point to /socket.io/ then i created another to point to the main api for /api
I have MERN app, the api build with express and the client build with reactjs.
In my local computer (windows), the client can connect to socket server. The onConnection event is triggered.
1. Local Computer (Windows)
Client Side:
socket.on('connect', () => {
console.log('connected to the socket server');
}) // triggered and i can see the console.log in broser console
Server Side:
io.on('connection', () => {
console.log('client connected to the socket server');
}) // triggered and i can see the console.log in terminal
2. VPS (Ubuntu 20, Nginx)
When i deploy the server and the client to vps, the socket can't connect. on connection event not triggered.
But the client is trigger connect_error event:
socket.on("connect_error", (error) => {
console.log('socket connection error:', error.message) // socket connection error: server error
}); // this event is triggered
This is my code:
Server side:
const server = app.listen(3000)
const io = socketio(server)
Client side:
const socket = io("http://103.150.60.132/api")
NGINX Config:
server {
listen 80;
location / {
root /var/www/bacotin/client; //reactjs build location
index index.html index.htm;
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/ /index.html;
}
location /api {
proxy_pass http://103.150.60.132:3000; // express api
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 ~* \.io {
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 false;
proxy_pass http://localhost:3000;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
UPDATE: the problem is solve, now the socket client can connect to the socket server.
Just modify the client code:
From this:
const socket = io("http://103.150.60.132/api")
To this:
const socket = io("http://103.150.60.132")
But why?
I Wonder how can i handle subdomains in my project that based on Expressjs.
Here's My nginx configuration
server {
listen 80;
server_name bee.local;
access_log /var/log/nginx/bee.local.access.log;
error_log /var/log/nginx/bee.local.error.log;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header X-Forwarded-For $remote_addr;
}
}
server {
listen 80;
server_name api.bee.local;
access_log /var/log/nginx/bee.local.access.log;
error_log /var/log/nginx/bee.local.error.log;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header X-Forwarded-For $remote_addr;
}
}
and here's my router with subdomain support
router.get('/v1/', function(req, res, next) {
res.status(200).json({ title: "title" });
});
app.use(subdomain('api', router));
The problem is that it's rendering the index route
and for sure i setuped the hosts file
I've been searching for 3 hrs can you help me :)
There are several requirements:
Setup Host header in nginx with required domain or proxy if applicable
Use subdomain middleware before other middlewares that handle endpoints
Work example:
nginx configuration:
server {
listen 80;
server_name bee.local;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
server {
listen 80;
server_name api.bee.local;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
nginx configuration with hardcoded Host header values:
I believe that you did not setup Host header correctly. please try next configuration
server {
listen 80;
server_name bee.local;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
# proxy_set_header Host $host;
proxy_set_header Host bee.local;
}
}
server {
listen 80;
server_name api.bee.local;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
# proxy_set_header Host $host;
proxy_set_header Host api.bee.local;
}
}
express app:
var subdomain = require('express-subdomain');
var express = require('express');
var app = express();
var router = express.Router();
router.get('/', function(req, res) {
res.send('Welcome to our API!');
});
router.get('/users', function(req, res) {
res.json([
{ name: "Brian" }
]);
});
app.use(subdomain('api', router));
app.get('/', function(req, res) {
res.send('Homepage');
});
app.listen(3000);
I'm trying to send back my index.html to the client when my nginx (acting as reverse proxy for my express application servers and to serve static assets) gets back a 404 from the API that it's proxying for.
This is the relevant server block for my nginx configuration:
server {
listen 80;
root /var/www/dist;
index index.html index.htm;
location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
expires 1d;
}
location #proxy {
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
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-NginX-Proxy true;
proxy_http_version 1.1;
proxy_redirect off;
proxy_pass http://node-app;
proxy_cache_bypass $http_upgrade;
}
location / {
try_files $uri $uri/ #proxy;
}
error_page 404 = /;
}
Just to specify, the use case here is I'm using React Router with HistoryLocation enabled, so right now if I try to refresh on one of my routes (like example.com/signup), I get back a 404.
When using an express server (including via nginx), send back index.html as a catch-all, after handling other file types:
app.get( /\.(js|css|png|jpg|svg)$/, function(req, res) {
var uri = url.parse( req.url, true, false );
sendFile( res, uri.pathname );
} );
//------------- return index.html for everything else so routing works
app.get( '*', function(req, res) {
sendFile( res, `${htmlPath}index.html` );
} );
If just using nginx directly (without express), return index.html for 404 errors:
error_page 404 /index.html;
location = /40x.html {
}