Angular client enable CORS - node.js

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

Related

HTTPS Server CORS Issue

So I have a NodeJS Express server which I am switching over from http to https. I have two files starting this:
app.js which defines the express part of the server, sets headers etc...
const express = require('express');
const app = express();
const dataRoutes = require('./routes/data');
app.use((req, res, next) => {
res.setHeader("Access-Control-Allow-Origin", "*"); //"https://www.wordleleague.org");
res.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization");
res.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
next();
})
app.use("/api/data", dataRoutes);
module.exports = app;
and server js which is the main part of the code, the launched file:
const app = require("./app");
const https = require("https");
const fs = require("fs");
const port = normalizePort(process.env.PORT || "3000");
app.set("port", port);
const httpsOptions = {
key: fs.readFileSync('key.pem'),
cert: fs.readFileSync('cert.pem')
};
const server = https.createServer(httpsOptions, app);
server.listen(port);
Whilst this all worked fine when I was using http, now I get a CORS error when trying to query this:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading
the remote resource at https://localhost:3000/api/data/login. (Reason:
CORS header ‘Access-Control-Allow-Origin’ missing). Status code: 499.
It looks like the express app object isnt being used by the createServer. This all worked in http but its when I tried adding the credentials to the object for https that it went wrong.
If there is any further info anybody needs I am happy to provide, but this seems like all that is relevant. The requests are not being routed to the appropriate method and the http call from the angular app is definatele working.
Edit - The call to the server and more error detail
This is the code which calls the server:
this.subscriptions['leaguesub'] = this.http.get<{success: boolean, data: League[]}>(environment.apiUrl+'api/data/all/userId=' + id).subscribe({
next: (result: {success: boolean, data: League[]}) => {
this.leaguesLocal = [...result.data];
this.leagues.next([...this.leaguesLocal]);
}})
Works fine when I am using http. The only header which is added is an authorisation token:
req.headers.set('Authorization', "Bearer " + token)
The error it seems is a 499:
Status 499 Request has been forbidden by antivirus Referrer Policy
strict-origin-when-cross-origin
edit 2
If I reverse the order of createserver arguments then the CORs issue goes away but I have a new, different CORs issue:
const server = https.createServer(app, httpsOptions);
Cross-Origin Request Blocked: The Same Origin Policy disallows reading
the remote resource at https://localhost:3001/api/user/login. (Reason:
CORS request did not succeed). Status code: (null).
One of the comments suggests using a CORs module but im not sure why my code isnt working
edit 3
Ok so I modified the main app.js express file to reflect the CORS suggestion made below:
const cors = require('cors');
const app = express();
app.use(cors());
And the error is persistent. Still no luck connecting to the server or any idea how to debug it. I tried using these methods to check a connection:
app.post("*", (req, res, next) => {
console.log(`post here`);
next();
})
app.get("*", (req, res, next) => {
console.log(`get here`);
next();
})
But alas I get no info from the concole about these running the event of a call being made to the API. Same errors as before.
edit 4
Running in Chrome gives me a new info source:
ERR_SSL_VERSION_OR_CIPHER_MISMATCH
Looking this up it seems there may be a problem with the SSL certificate. It is a self created SSL certificate which normally requires you to press ALLOW or something. It would explain why there seems to be nothing getting through to the server whatsoever as my browser is blocking it.
The problem then it how to get around this?

XMLHttpRequest at from origin has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource

I am facing an issue with REST APIs. My front-end is in React and APIs are in Express. I intermittently get below error. I've gone through many other similar posts and tried to add HTTP headers to the response without any luck. These calls works fine from Postman client.
"from origin 'http://localhost:3000' has been blocked by CORS policy:
No 'Access-Control-Allow-Origin' header is present on the requested
resource."
So, far I've added below lines to populate HTTP response. The MOST annoying part is these errors only happens with certain web services and not others. They all are identically coded so, it makes it difficult to determine why in certain cases it fails.
My server.js (Express REST app) is as per below ...
const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');
const app = express();
const controllers = require('./controllers');
const logger = require('./logger/logger');
const port = 9000;
app.use(bodyParser.urlencoded({ extended: true }))
app.use(bodyParser.json());
app.use(bodyParser.raw());
controllers.init(app);
app.use(cors());
//Listen server on define port
var server = app.listen(port, () => {
logger.info("API Server is running on port " + port);
})
So, far what I've noticed is, when I add the below segment to include HTTP response headers in my controllers (controllers uses services and models to serve requests), the error disappears EVEN if I remove them after first successful call from my React front-end and this is really bizarre. I use Chrome to test my React front-end. Does this mean Chrome browser is caching something esp. when it comes to the origin? I am worried how this will span out in production? has anyone experienced this sort of behaviour?
app.use((req, res, next) => {
res.append('Access-Control-Allow-Origin', "*");
res.append('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
res.append('Access-Control-Allow-Headers', 'Content-Type');
next();
});
Below are the packages I use for the Express API server ..My React front-end uses "react": "^16.13.1"
"dependencies": {
"body-parser": "^1.19.0",
"cors": "^2.8.5",
"express": "^4.17.1",
ok, just managed to get this work by adding the below segment
controllers.init = function (app) {
app.use((req, res, next) => {
res.append('Access-Control-Allow-Origin', '*');
res.append('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
res.append('Access-Control-Allow-Headers', 'Content-Type');
next();
});
in my index.js under controllers folder. index.js contains init for all other controllers....see below
(function (controllers) {
var appMenuController = require("./appMenuController");
var applicantTypeController = require("./applicantTypeController");
var permitApplicationController = require("./permitApplicationController");
var campusController = require("./campusController");
var paymentMethodController = require("./paymentMethodController");
var permitTypeController = require("./permitTypeController");
var permitController = require("./permitController");
var permitChangeRequestController = require("./permitChangeRequestController");
var requestTypeController = require("./requestTypeController");
var vehicleController = require("./vehicleController");
controllers.init = function (app) {
app.use((req, res, next) => {
res.append('Access-Control-Allow-Origin', '*');
res.append('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
res.append('Access-Control-Allow-Headers', 'Content-Type');
next();
});
appMenuController.init(app);
applicantTypeController.init(app);
permitApplicationController.init(app);
campusController.init(app);
paymentMethodController.init(app);
permitTypeController.init(app);
permitController.init(app);
permitChangeRequestController.init(app);
requestTypeController.init(app);
vehicleController.init(app)
}
})(module.exports);
I still don't get it i.e. why Chrome (even Firefox) won't allow HTTP REQ\RESP comms between 2 localhosts on the same host i.e. localhost. Where is a threat in responses originating from the localhost? unless I misunderstood CORS

CORS Header Issue between react / express

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.

No 'Access-Control-Allow-Origin' header is present on the requested resource in angular app

I've angular cli project that hosted in azure and I'm making API call to different domain (in Zoho creator) so I have CROS issue I tried some solutions with no luck.
The error is
"Access to XMLHttpRequest at "https://xxxxxxx" from origin "https://yyyyyy" has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource."
I use expressJS as my backend and I tried to add headers but it seems not working I don't know what I'm missing
APP.JS
const express = require('express');
const bodyParser = require('body-parser');
const path = require('path');
const http = require('http');
const app = express();
// parse application/x-www-form-urlencoded
var cors = require('cors');
// Use this after the variable declaration
app.use(cors({origin: '*'}));
// parse application/json
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
// Angular DIST output folder
app.use(express.static(path.join(__dirname, 'dist')));
// Send all other requests to the Angular app
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, 'dist/index.html'));
});
// Add headers
app.use(function (req, res, next) {
// Website you wish to allow to connect
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:5000');
// Request methods you wish to allow
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
// Request headers you wish to allow
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
// Set to true if you need the website to include cookies in the requests sent
// to the API (e.g. in case you use sessions)
res.setHeader('Access-Control-Allow-Credentials', true);
// Pass to next layer of middleware
next();
});
//Set Port
const port = process.env.PORT || '5000';
app.set('port', port);
const server = http.createServer(app);
server.listen(port, () => console.log(`Running on localhost:${port}`));
I don't recognize exactly what It's happening but there's something that it makes me noise.
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:5000');
This code indicate that you can only receive requests from http://localhost:5000. Are you trying to consume it from http://localhost:5000? I don't think so because the port 5000 is being used by node.js. if you want to use it, you must set Access-Control-Allow-Origin to the Server or Site where you're trying consume it from.
Example, I have a application in Angular in my machine using the port 4200, so the request header should be:
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:4200');
Or, you can use * to allow everything but It's not secure.
res.setHeader('Access-Control-Allow-Origin', '*');

Angular `CORS` policy Eroro

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.

Resources