I’m using the MEAN stack (MongoDB, Express, Angular, and NodeJS).
There is a simple function to get data from an external API like this:
let api = 'https://thongtindoanhnghiep.co/api/city';
return this.http.get<any>(api).subscribe(res => { this.data = res; });
But whenever it sends a request, I get the following error:
"OPTIONS https://thongtindoanhnghiep.co/api/city 405 (Method Not Allowed)
Access to XMLHttpRequest at 'https://thongtindoanhnghiep.co/api/city' from origin 'http://localhost:4040' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status."
My Chrome has web security disabled, with the CORS extension installed, and my app is configured to enable CORS on the server side.
When I use Postman to do this, it is working well.
In node js you have fix this issue in 2 type
Type 1
install cors
npm install cors
var express = require('express')
var cors = require('cors')
var app = express()
app.use(cors())
// cors config
app.use(function (req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Methods", "GET,HEAD,OPTIONS,POST,PUT,DELETE");
res.header("Access-Control-Allow-Headers", "*");
next();
});
app.listen(8083, () => {
console.log('Server connected with 8083');
})
Type 2
npm install browser-sync --save
var fs = require('fs');
var http = require('http');
var https = require('https');
var privateKey = fs.readFileSync('node_modules/browser-sync/certs/server.key', 'utf8');
var certificate = fs.readFileSync('node_modules/browser-sync/certs/server.crt', 'utf8');
var credentials = {key: privateKey, cert: certificate};
var httpServer = http.createServer(app);
var httpsServer = https.createServer(credentials, app);
httpServer.listen(8080,()=>{
console.log('Server connected with 8080');
});
httpsServer.listen(8081,()=>{
console.log('Server connected with 8081');
});
In that way you provide express middleware to the native http/https server
If you want your app running on ports below 1024, you will need to use sudo command (not recommended) or use a reverse proxy (e.g. nginx, haproxy).
You can use this in your Node.js application entry point
var cors = require('cors')
app.use(cors())
Or
You can use response object to set the header
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
Hopefully this should solve the problem.
Related
I'm using Express.js with the CORS middleware. I'm getting very strange behavior on Firefox v73.0.1 (64-bit)
Clean firefox profile... so nothing is cached.
I try a direct request to http://localhost/search?q=AMZN, I get results as expected.
I open my webapp which is running on localhost:3000. All of these requests are not using TLS/SSL.
I get "Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost/search?q=AMZN. (Reason: CORS request did not succeed)." when it tries to reach out to the API server backend.
I refresh the other tab where I was accessing localhost directly (same request which succeeded before), and I get a "connection reset".
Chrome does not do this...
I have been looking at wireshark and Firefox simply sends a GET request (several of them? Why?? I'm only making one), sends the headers and such, then it is followed by connection reset.
Sounds like node is doing something wrong? Or I dunno.
const express = require('express');
const fetch = require('node-fetch');
const util = require('util');
const app = express();
const port = 80;
var cors = require('cors')
var copts = {
origin: function (origin, callback) {
console.log('yeah');
// allow all
callback(null, true);
}
}
const SEARCH_URL = 'https://api.stocktwits.com/api/2/streams/symbol/%s.json';
app.get('/search', cors(copts), (req, res) => {
The "yeah" part never is hit at all.
Very simple clientside code.
return fetch(BACKEND_URL + uri).then(response => {
Tried removing CORS middleware and added these headers, based on examining github's cross-browser request-response in chrome
res.header('Access-Control-Allow-Methods', 'GET');
res.header('Access-Control-Max-Age', '3600');
res.header('Vary', 'Origin, Access-Control-Request-Headers, Access-Control-Request-Method, Accept-Encoding');
res.header('Access-Control-Allow-Origin', '*');
I didn't really have the options handler captured so maybe this didnt matter. I found those headers in the GET response.
It might be possible that the node server get crashed on an invalid reqeust and hence you are getting the reset error.
With cors package:
You need to add optionsSuccessStatus property in the cors options for some legacy browsers. And OPTIONS handler To enable pre-flightin requests.
const express = require('express');
const fetch = require('node-fetch');
const util = require('util');
const app = express();
const port = 80;
var cors = require('cors')
var copts = {
origin: function (origin, callback) {
console.log('yeah');
callback(null, true);
},
optionsSuccessStatus: 200
}
app.options("*", cors(copts));
const SEARCH_URL = 'https://api.stocktwits.com/api/2/streams/symbol/%s.json';
app.get('/search', cors(copts), (req, res) => { });
With headers.:
You are missing Access-Control-Allow-Headers in the response headers, you need to add the Access-Control-Allow-Headers header in the response header to allow the Access-Control-Allow-Origin header.
Try this.
const express = require('express');
const fetch = require('node-fetch');
const util = require('util');
const app = express();
const port = 80;
var cors = require('cors')
var copts = {
origin: function (origin, callback) {
console.log('yeah');
// allow all
callback(null, true);
}
}
const SEARCH_URL = 'https://api.stocktwits.com/api/2/streams/symbol/%s.json';
app.get('/search', (req, res) => {
res.header('Access-Control-Allow-Methods', 'GET, OPTIONS');
res.header('Access-Control-Allow-Headers', 'Origin');
res.header('Access-Control-Allow-Origin', '*');
res.status(200).send("Ok")
});
in my case, FireFox removes the request header from ajax to a http url, but works fine with https
Have you updated your front end package.json file with the following?
"proxy": "http://localhost:[your port here]/",
try assigning CORS to the express server like so:
const cors = require('cors');
app.use(cors());
I'm having a problem with CORS, despite reading and implementing various solutions on SO.
I have an app that uses Express/NodeJS as an api and React JS as a front end.
In development, the react app http://localhost:3000 is able to talk to the express backend http://localhost:9000with app.use(cors()).
Now I'm trying to use this app in production.
Both apps are kept in separate git repositories.
React is deployed as a static website on aws s3 and works fine.
Node JS is deployed on Elastic Bean Stalk and is in the ready state.
I have a Postgres SQL database attached to the ebs instance(node app) that I'm able to connect to in pgadmin4.
Both apps are using the same base domain in route 53 myproject.com.
Both are configured to listen for https/443. I can hit both URLS https://myproject.com and https://api.myproject.com & they look like how they do in my localhost environment.
When I try to signup a user on my site I run into this error:
Access to XMLHttpRequest at 'https://api.myproject.com/users/signup/' from origin 'https://myproject.com' has been blocked by CORS policy:
No 'Access-Control-Allow-Origin' header is present on the requested resource.
Both apps are able to "see" each other but that's about where it ends.
Looking at my code, I can't figure out where the issue is taking place:
server.js
const express = require('express');
const cors = require('cors');
const logger = require('morgan');
const bodyParser = require('body-parser');
require('dotenv').config();
const PORT = process.env.PORT || 9000; // DEV
const app = express();
const corsOptions = {
origin: 'https://myproject.com',
optionsSuccessStatus: 200 // some legacy browsers (IE11, various SmartTVs) choke on 204
}
const allowCrossDomain = function (req, res, next) {
res.header('Access-Control-Allow-Origin', 'https://myproject.com');
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
res.header('Access-Control-Allow-Headers', 'Content-Type');
next();
}
app.use(cors());
const { userRouter } = require('./routes/userRouter');
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(allowCrossDomain);
app.use((e, req, res, next) => {
res.header("Access-Control-Allow-Origin", "https://myproject.com");
res.header('Access-Control-Allow-Methods', 'DELETE, PUT, GET, POST');
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
if (e) {
console.log(e);
res.status(500).send(e.message);
}
next();
});
app.use('/users', userRouter);
app.listen(PORT, () => {
console.log(`Express server is listening on PORT ${PORT}.`);
});// - TESTING
What I've tried:
Most of these solutions came from this SO post: Why doesn't adding CORS headers to an OPTIONS route allow browsers to access my API?
Using just app.use(cors());
Using a wildcard * instead of a domain name.
White listing my domain with cors (from this blog post): https://daveceddia.com/access-control-allow-origin-cors-errors-in-react-express/
// Set up a whitelist and check against it:
var whitelist = ['https://myproject.com']
var corsOptions = {
origin: function (origin, callback) {
if (whitelist.indexOf(origin) !== -1) {
callback(null, true)
} else {
callback(new Error('Not allowed by CORS'))
}
}
}
// Then pass them to cors:
app.use(cors(corsOptions));
I've also moved app.use(cors()) above my routes as suggested in another StackOverflow post.
At this point, I'm stuck so any help is appreciated so thanks in advance.
Try requiring cors this way:
const cors = require('cors')({
origin: 'https://yourdomain.com',
});
This way you can add origin and then just call app.use(cors()) at the top of the express app
const app = Express();
app.use(BodyParser.json());
app.use(cors);
this is the way I usually get things to work. Another factor you may be dealing with is if the domain hasn't fully propagated yet, this may be causing your regions for aws to not recognize the domain's dns. That's just a theory though.
CORS is fine on server and works as intended. I tried sending requests to my server's REST API with the angular HTTPClient and I receive a CORS error.
Why is this an error if CORS is enabled on the server? Shouldn't it be fine on the client?
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:3000/api/blah/blah (Reason: CORS header ‘Access-Control-Allow-Origin’ missing).
How can I enable CORS on this request please.....
For future refrence it was "Davids" answer that assisted me, the cors was not added before all routing.
"..... Meaning, before the route is defined."
so right after ...
var app = express();
I just use...
app.use(cors());
A little intro:
Cross-Origin Resource Sharing aka CORS is a mechanism that uses additional HTTP headers to tell browsers to give a web application running at one origin (e.g. http://localhost:3000), access to selected resources from a different origin (e.g. http://localhost:8080). In other words, a web app executes a cross-origin HTTP request when it requests a resource that has a different origin (domain, protocol, or port) from its own. For security reasons, browsers restrict cross-origin HTTP requests initiated from scripts.
The Access-Control-Allow-Origin header determines which origins are allowed to access server resources over CORS.
How to Fix CORS Issues?
You can do it yourself by creating an Express middleware. Here's the appropriate code snippet:
// Enable CORS for specific origins:
app.use((req, res, next) => {
// Allow multiple predefined origins
const allowedOrigins = ["https://deployed-app.com", "http://localhost:3000"];
const origin = req.headers.origin; // extract the origin from the header
if (allowedOrigins.indexOf(origin) > -1) { // if the origin is present in our array
res.setHeader("Access-Control-Allow-Origin", origin); // set the CORS header on the response
}
res.header(
"Access-Control-Allow-Headers",
"Origin, X-Requested-With, Content-Type, Accept"
);
next(); // move on to the next middleware
});
Alternatively, you can accept all requests,
but this option is only appropriate if you're in development or if your API is public :)
app.use((req, res, next) => {
res.header("Access-Control-Allow-Origin", "*");
next();
});
Additionally, there's an Express CORS middleware and this is how you would use it:
npm install cors --save
Enable All CORS Requests:
const express = require('express');
const cors = require('cors');
const app = express();
app.use(cors());
app.get('/products/:id', function (req, res, next) {
res.json({msg: 'This is CORS-enabled for all origins!'})
});
const port = process.env.PORT || 8080;
app.listen(port, () => {
console.log(`CORS-enabled server is up on ${port}`);
});
Enable CORS for a Single Route
const express = require('express');
const cors = require('cors');
const app = express();
app.get('/products/:id', cors(), (req, res, next) => {
res.json({msg: 'This is CORS-enabled for a Single Route'})
});
const port = process.env.PORT || 8080;
app.listen(port, () => {
console.log(`CORS-enabled server is up on ${port}`);
});
Important gotcha: When it comes to Express middleware, the order is very important. So make sure CORS is enabled before any other controller/ route/ middleware which may depend on it.
You dont need to enable cors in angular, this is a server side issue. See:
https://stackoverflow.com/a/29548846/4461537
I want to connect with socket.io to a backend that uses express.
the backend is used as api for other functionalities. So, I use some middleware to add headers to express (you could see that in the code).
the problem is that the socketio on the client side gives the following error:
The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'.
but I need to keep the '*' to allow all users from any where to access my api.
var express = require('express'); var server = express();
var app = require('http').Server(server);
var io = require('socket.io')(app);
io.set( "Access-Control-Allow-Origin", "*" );
require('./controllers/watsonIoT.controller').startWatson(io);
server.use(function(request, response, next) { // configuration of headers
response.header("Access-Control-Allow-Origin", "*");
response.header("Access-Control-Allow-Headers", "Content-Type, x-auth");
response.header("Access-Control-Allow-Methods", "GET,POST,DELETE,PUT")
next();
})
.use('/gui', express.static('views'))
.use(bodyParser.json())
.use('/api', mainRouter)
.get('*', (req, res) => res.redirect('/'))
.listen(PORT,function(){
console.log("Starting ... port: "+ PORT);
// startWatson();
});
I am trying to display a dicom with NODEJS but the browser throws me this problem
XMLHttpRequest can not load http: // localhost: 8080 / wado?
RequestType = WADO & studyUID = 1.2.840.113704.1.111.5 ... 26513.429 &
contentType = application% 2Fdicom & transferSyntax =
1.2.840.10008.1.2. In 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http: // localhost: 3000' is
therefore not allowed access.
Then install npm the package cors
And here I leave my code part of my code app.js
Var express = require ('express');
Var cors = require ('cors')
App.use (cors ())
App.listen (3000, function () {
Console.log ('listening on 3000')
})
Also try adding this in app.js
App.use (function (req, res, next) {
Res.header ("Access-Control-Allow-Origin", "*");
Res.header ("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
Next ();
});
But the browser still displays the error:
XMLHttpRequest can not load http: // localhost: 8080 / wado?
RequestType = WADO & studyUID = 1.2.840.113704.1.111.5 ... 26513.429 &
contentType = application% 2Fdicom & transferSyntax =
1.2.840.10008.1.2. In 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http: // localhost: 3000' is
therefore not allowed access.
I have doubt because I also use the route index.js which I leave here
var express = require('express');
var router = express.Router();
var cors = require('cors')
/*var express = require('express');
var router = express.Router();*/
var mysql = require('mysql');
router.use(cors({origin: 'http://localhost:3000'}));
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('index', { title: 'Express' });
});
module.exports = router;
I'm sorry for my English
For security purpose browsers don't allow cross origin requests under normal conditions.
Your page is loading from localhost:3000, which defines the origin as it is the first request. Your code is trying to load data from another service running on port- 8080, that is different from origin. So basically you need to enable cors on the service running on port 8080 as it is the external source.