I have an expressjs app behind nginx server already importing and using cors
module.
var express = require("express");
var cors = require("cors");
var app = express();
var corsOptions = {
origin: "http://localhost:3000",
credentials: true,
optionSuccessRate: 200
};
app.use(cors(corsOptions));
app.options("*", cors());
I send a POST request via XMLHttpRequest to upload the file to the server from localhost client. At first, the requests were going through successfully without any error. But randomly after tries, I started to get the following error followed by 502 bad gateway error.
Access to XMLHttpRequest at SERVER_DOMAIN from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
POST SERVER_DOMAIN net::ERR_FAILED 502 (Bad Gateway)
Nginx Config
etc/nginx/nginx.conf
user www-data;
worker_processes auto;
pid /run/nginx.pid;
error_log /var/log/nginx/error.log;
include /etc/nginx/modules-enabled/*.conf;
events {
worker_connections 768;
# multi_accept on;
}
http {
sendfile on;
tcp_nopush on;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE
ssl_prefer_server_ciphers on;
access_log /var/log/nginx/access.log;
gzip on;
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
client_max_body_size 100M;
}
/etc/nginx/sites-available/default
server {
server_name DOMAIN_NAME;
location / {
proxy_pass http://127.0.0.1:5000;
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_redirect off;
proxy_request_buffering off;
}
listen [::]:443 ssl ipv6only=on; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/[DOMAIN_NAME]/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/[DOMAIN_NAME]/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 = DOMAIN_NAME) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80 default_server;
listen [::]:80 default_server;
server_name DOMAIN_NAME;
return 404; # managed by Certbot
}
And my express app. Note that I'm using PM2 to run it.
import fs from "fs";
import path from "path";
import cors from "cors";
import express from "express";
import formidable from "formidable";
import someFunction from "./someFunction.js";
const app = express();
var corsOptions = {
origin: "http://localhost:3000",
credentials: true,
optionSuccessStatus: 200
};
app.use(cors(corsOptions));
app.options("*", cors());
const port = 5000;
const __dirname = path.resolve();
app.post("/", function(req, res, next) {
const form = formidable({
uploadDir: "uploads"
});
form.parse(req, function(err, fields, files) {
try {
if(err) {
next(err);
res.send("Error");
}
const metadata = JSON.parse(fields["config"][0]);
const dir = `${form.uploadDir}/${metadata.dir}`;
const fileName = files["files"][0].originalFilename;
fs.mkdirSync(dir);
fs.rename(files["files"][0].filepath, `${dir}/${fileName}`, function(err) {
if(err) throw err;
});
// do conversion here-------------------------
someFunction(fileName, metadata)
.then(() => {
res.write("Done");
res.end();
})
.catch(er => {
throw er;
});
//--------------------------------------------
}catch(e) {
console.log(e);
res.write("Error");
res.end();
}
});
});
app.listen(port, function() {
console.log("Server initialized");
});
I have checked the app. Interestingly, it executes successfully all the way till the someFunction
. I have also checked PM2 and it is active/working.
It looks as if in writing a response res.write
, it is failing.
In a last bit of hope, I checked the nginx log. And I have caught an error there. It says connection refused while trying to connect to upstream client with the following request:
request: "GET /?name=example&type=A HTTP/1.1", upstream: "http://127.0.0.1:5000/?name=example&type=A", host: "........."
I don't understand from where the example
is coming in the request instead of my custom domain. Any misconfiguration of nginx?
Can someone please tell what is wrong and how to fix it?
I have an expressjs app behind nginx server already importing and using cors
module.
var express = require("express");
var cors = require("cors");
var app = express();
var corsOptions = {
origin: "http://localhost:3000",
credentials: true,
optionSuccessRate: 200
};
app.use(cors(corsOptions));
app.options("*", cors());
I send a POST request via XMLHttpRequest to upload the file to the server from localhost client. At first, the requests were going through successfully without any error. But randomly after tries, I started to get the following error followed by 502 bad gateway error.
Access to XMLHttpRequest at SERVER_DOMAIN from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
POST SERVER_DOMAIN net::ERR_FAILED 502 (Bad Gateway)
Nginx Config
etc/nginx/nginx.conf
user www-data;
worker_processes auto;
pid /run/nginx.pid;
error_log /var/log/nginx/error.log;
include /etc/nginx/modules-enabled/*.conf;
events {
worker_connections 768;
# multi_accept on;
}
http {
sendfile on;
tcp_nopush on;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE
ssl_prefer_server_ciphers on;
access_log /var/log/nginx/access.log;
gzip on;
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
client_max_body_size 100M;
}
/etc/nginx/sites-available/default
server {
server_name DOMAIN_NAME;
location / {
proxy_pass http://127.0.0.1:5000;
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_redirect off;
proxy_request_buffering off;
}
listen [::]:443 ssl ipv6only=on; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/[DOMAIN_NAME]/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/[DOMAIN_NAME]/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 = DOMAIN_NAME) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80 default_server;
listen [::]:80 default_server;
server_name DOMAIN_NAME;
return 404; # managed by Certbot
}
And my express app. Note that I'm using PM2 to run it.
import fs from "fs";
import path from "path";
import cors from "cors";
import express from "express";
import formidable from "formidable";
import someFunction from "./someFunction.js";
const app = express();
var corsOptions = {
origin: "http://localhost:3000",
credentials: true,
optionSuccessStatus: 200
};
app.use(cors(corsOptions));
app.options("*", cors());
const port = 5000;
const __dirname = path.resolve();
app.post("/", function(req, res, next) {
const form = formidable({
uploadDir: "uploads"
});
form.parse(req, function(err, fields, files) {
try {
if(err) {
next(err);
res.send("Error");
}
const metadata = JSON.parse(fields["config"][0]);
const dir = `${form.uploadDir}/${metadata.dir}`;
const fileName = files["files"][0].originalFilename;
fs.mkdirSync(dir);
fs.rename(files["files"][0].filepath, `${dir}/${fileName}`, function(err) {
if(err) throw err;
});
// do conversion here-------------------------
someFunction(fileName, metadata)
.then(() => {
res.write("Done");
res.end();
})
.catch(er => {
throw er;
});
//--------------------------------------------
}catch(e) {
console.log(e);
res.write("Error");
res.end();
}
});
});
app.listen(port, function() {
console.log("Server initialized");
});
I have checked the app. Interestingly, it executes successfully all the way till the someFunction
. I have also checked PM2 and it is active/working.
It looks as if in writing a response res.write
, it is failing.
In a last bit of hope, I checked the nginx log. And I have caught an error there. It says connection refused while trying to connect to upstream client with the following request:
request: "GET /?name=example&type=A HTTP/1.1", upstream: "http://127.0.0.1:5000/?name=example&type=A", host: "........."
I don't understand from where the example
is coming in the request instead of my custom domain. Any misconfiguration of nginx?
Can someone please tell what is wrong and how to fix it?
Share Improve this question edited Mar 25 at 3:02 Waleed93 asked Mar 22 at 23:54 Waleed93Waleed93 1,3103 gold badges21 silver badges24 bronze badges 7- Is that the full express code? There's no post endpoint and it's not listening... – pguardiario Commented Mar 23 at 1:27
- Yes, it is listening to the port, and there's an endpoint. But I didn't add the code as I believe they are irrelevant – Waleed93 Commented Mar 23 at 1:58
- 2 It's hard to say without seeing full code but the 502 would be coming from nginx so maybe express is down – pguardiario Commented Mar 23 at 3:20
- I am happy to share. Is it the nginx config or expressjs code I share? – Waleed93 Commented Mar 23 at 3:44
- How come did an untouched previously running expressjs app suddenly got down? It's a very simple app that just has a POST endpoint to upload a file. – Waleed93 Commented Mar 23 at 3:47
1 Answer
Reset to default 0The CORS error is a symptom, not the root cause. The real issue is your Express app is likely down or unresponsive, which causes Nginx to return a 502 Bad Gateway
, and without a response from Express, there are no CORS headers to return, triggering the browser error
- Check if Express is still running.
curl http://localhost:<your-express-port>
- Check Nginx config.
Make sure your
proxy_pass
points to the correct running port and doesn't buffer or cache stale connections. Example:
location / {
proxy_pass http://localhost:5000; # Replace with your Express port
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;
}
- Avoid
cors()
in.options("*", cors())
That line overrides your originalcorsOptions
. Instead do:
app.options("*", cors(corsOptions));
You're seeing CORS errors because Nginx can't reach Express > 502. Fix the Express process or Nginx proxy config. Make sure you use app.options("*", cors(corsOptions))
, not cors()
with default values