Cannot set headers for Express.js app (CORS) - node.js

No matter what I try to use to set the headers it simply won't work.
The server side needs to send the response headers like this, after accepting the POST request from Frontend.
server.js
app.post('/register', (req, res) => {
res.set({
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
});
res.send('string');
res.end();
}
The res.set() function was not the only function I tried to use.
I tried with:
res.writeHead(201, {'Access-Control-Allow-Origin': '*'}) - doesn't work
res.setHeader('Access-Control-Allow-Origin', '*') - nope
res.headers() - also doesn't work
It says here that it goes like this: How can I set response header on express.js assets but the answer doesn't work for me.
No matter what I tried, the server just won't respond with the CORS enabled header and I need that header property. What am I doing wrong?

Try using the cors module: https://www.npmjs.com/package/cors
var cors = require('cors')
...
app.use(cors())

The Access-Control-Expose-Headers response header indicates which headers can be exposed as part of the response by listing their names.
You can read more about it here: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Expose-Headers
res.set('Access-Control-Expose-Headers', 'Access-Control-Allow-Origin, <any-other-custom-header>, ...');

Related

No CORS error when making GET requests, but CORS error when making POST requests

I have a Node/Express server that interacts with a React app.
I need to make POST and GET requests, the problem is that when making POST requests I get a CORS error, the usual:
Access to fetch at 'http://localhost:9000/testAPI' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
I specified on the response on the server the Access-Control-Allow-Origin header, but I am not sure if I have to set this header for a POST request as well. And if I do, what domain should it specify?
I am also not willing to use hacks like CORS extensions, or npm packages. I want to use CORS.
The server-side looks like so:
const express = require("express");
const router = express.Router();
router.get("/", (req, res, next) => {
console.log(req.url);
res.setHeader("Access-Control-Allow-Origin", "http://localhost:3000");
res.send("API is working properly");
});
module.exports = router;
In the React app, the GET request looks like so (works just fine):
const res = await fetch('http://localhost:9000/testAPI');
console.log(res);
The POST request looks like so (CORS error thrown):
const res = await fetch('http://localhost:9000/testAPI', {
method: 'POST',
mode: 'cors',
cache: 'no-cache',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ someData: "POST requests are working properly" })
});
Do I need to specify some additional headers or properties on the POST request? Or do I have to modify something on the server-side?
If I will not have this problem when going live, than I do not mind using a hack like CORS extension.
You may use this package cors
// Install
npm install cors
yarn add cors
// server.js
const express = require('express');
const cors = require('cors');
const app = express();
// global middleware
app.use(cors());
// You can use route based middleware too
router.post("/", cors(), (req, res, next) => {
// process request & send response to client
});

new HttpHeaders().set() does not set headers - Ionic/Angular

I'm creating a little app using NodeJs and Ionic v3 and I'm stuck with CORS error:
Failed to load http://localhost:3000/crm/getAllClients: Response to
preflight request doesn't pass access control check: No
'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'http://localhost:8100' is therefore not allowed
access.
I've set CORS in nodeJs like this:
app.use(cors());
To make HTTP request with Ionic I'm using :
import {HttpClient, HttpHeaders} from "#angular/common/http";
Here's my code in my Ionic service:
initHeaders() {
let headers = new HttpHeaders()
.set('Access-Control-Allow-Origin', "*")
.set("Content-Type", "application/json")
.set("Access-Control-Expose-Headers", "Content-Length");
return headers;
}
getAllClients () {
return this.http.get(this.domain + 'crm/getAllClients', {headers: this.initHeaders()});
}
Here are the headers with no header set:
Am I doing something wrong ?
I had a similar issue in the past. As far as I understand you are not doing anything wrong, your three headers are inside "Access-Control-Request-Headers" (in your screenshot under "Request Headers".
The browser joins all your CORS headers and puts them in "Access-Control-Request-Headers".
My bet is that there is a problem with the cors configuration in node. I would try something like this in you express app:
app.use(function (req, res, next) {
res.header("Access-Control-Allow-Headers", "Access-Control-Expose-Headers, Content-Type, Accept");
next();
});
instead of using
app.use(cors())
Or check that you are writing app.use(cors()) before adding the routes, so that the routes are using cors.
My problem was that I called cors Middleware after I've set routes on my app.js in node !
// set it before routes !
app.use(cors());
app.use('/', index);
app.use('/crm', crm);

Axios can't set headers after they are sent

I'm trying to use Axios in node like I would use something like CURL. I am making an api request to my node endpoint. I then use Axios to make a request to Spotify to do some OAuth stuff. I get the response back from the Axios request successfully but when I try and return a response in Express I am told the headers have already been sent. Below is a test I have set up to isolate the issue. This give the error "Can't set headers after they are sent".
makeRequest: function(req, res, next) {
axios.get('https://google.com')
.then(function(){
res.status(200).send({});
});
}
Can this be done? Thanks.
I think because I was modifying the headers of every request it was causing some problems, e.g.
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,PATCH');
I used a different router for the requests that I use Axios and it works OK now. Something like:
app.use('/api', apiRouter);
app.use('/callback', axiosRouter);
apiRouter.use(function(req, res, next) {
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,PATCH');
}
//I don't modify the axiosRouter headers

No 'Access-Control-Allow-Origin' is present, Origin 'null' not allowed access - Passport-SteamStrategy, Node

I have a site that is using Passport Steam Strategy. My server (Node with Express) is currently running on localhost:3000 while my front end is running on localhost:8080. I keep running into a cross-origin issue, only when attempting to authorize through Steam. My requests are made through Axios and I am using CORS. I've spent hours Googling and trying various things but I can't seem to get it to work.
This is the error that I get:
XMLHttpRequest cannot load
https://steamcommunity.com/openid/login?openid.mode=checkid_setup&openid.ns…3000%2Fsteam%2Fauth%2Freturn&openid.realm=http%3A%2F%2Flocalhost%3A3000%2F.
No 'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'null' is therefore not allowed access.
Here is where the route is called from the front end:
linkSteam(){
api('http://localhost:3000/steam/auth')
.then(res => {
console.log(res);
state.user = res.data.user;
})
}
And here is my axios configuration on the front end.
let api = axios.create({
baseURL: 'http://localhost:3000/api/',
timeout: 3000,
withCredentials: true
})
My CORS is set up as follows
var whitelist = ['http://localhost:8080', 'https://steamcommunity.com', 'http://localhost:3000', 'null'];
// I added null here as someone said that it worked as their origin displayed null like mine does
var corsOptions = {
origin: function (origin, callback) {
var originIsWhitelisted = whitelist.indexOf(origin) !== -1;
callback(null, originIsWhitelisted);
},
credentials: true
};
I then import my CORS into my main file and use it as follows
app.use(cors(corsOptions))
app.use('*', cors(corsOptions))
I kept seeing that you can set your Access-Control-Allow-Credentials, etc and did so
app.use(function (req, res, next) {
res.setHeader('Access-Control-Allow-Credentials', true);
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:8080');
res.setHeader('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With, X-HTTP-Method-Override, Content-Type, Accept');
if ('OPTIONS' == req.method) {
res.send(200);
} else {
next();
}
});
This didn't help. I've tried breaking down my original function where /steam/auth is called and running a console.log(req.headers.origin) and spits back my correct URL, but then the error still reports that the Origin is null. If I set my Access-Control-Allow-Origin' to '*', I get a slightly different error that I must provide credentials, and that the Origin 'localhost:8080' is therefore not allowed.
Here's my /steam/auth route.
router.get('/steam/auth',
passport.authenticate('steam', {
failureRedirect: '/'
}),
function (req, res) {
res.redirect('/');
});
And this does work if I click on the URL that cannot be loaded and then login to Steam. It will then redirect me back to my site with my Steam profile information intact. The error is on attempting to get the initial redirect back to Steam in order to login. I have also tried doing this in a res.redirect to their direct URL and I get the same error.
Thanks in advance for any help! And let me know if I'm missing vital information. I've tried to include everything, but I wouldn't be surprise if I missed something.
If the error message in the question is the actual message the browser is reporting, it’s because your client-side code is trying to send a request to https://steamcommunity.com/openid/login.
So given that, no matter what config changes you make to your Node server on localhost:3000, that’s not going to change anything. Instead it seems like you you need to figure out where your client-side code is sending a request to https://steamcommunity.com/openid/login and why.
And the reason the request to https://steamcommunity.com/openid/login fails is that server doesn’t include the Access-Control-Allow-Origin response header in its response.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS has more details.
So because you can’t change the server’s behaviour, your browser will continue so block your code from getting at the response as long as it lacks the Access-Control-Allow-Origin header.
I don’t know how authorization is handled by Steam but maybe you instead need to either make the authorization request to Steam through your existing Node backend somehow, or else set up your own CORS proxy using, e.g., https://github.com/Rob--W/cors-anywhere/, and proxy your client-side authorization request to Steam through it.

Angular 2 CORS issues

I have the following Angular 2 http request;
const endpoint = '<auth_url>';
const body = {
prompt: 'consent',
grant_type: 'authorization_code',
redirect_uri: '<redirect_url>',
code: '<authorization_code>'
};
const headers = new Headers();
headers.append('Authorization', 'Basic <auth>');
headers.append('Content-Type', 'application/x-www-form-urlencoded')
const options = new RequestOptions({ headers });
this.http.post(endpoint, body, { headers: headers })
.map(res => res.json())
.subscribe(
data => console.log(JSON.stringify(data)),
error => console.error(JSON.stringify(error)),
() => console.log('Request complete')
);
This is connecting to a node-oidc-provider which has been attached to an ExpressJS instance, the issue I am having is with CORS as the request ends up as OPTIONS on the server because of preflight. This shouldn't be the case as I have specified the Content-Type header as seen above. Annoyingly I am trying to figure out whether this is an issue with the server or my Angular2 code?
Would I need to explicitly enable CORS on an ExpressJS application and if not, why would setting the correct header on the POST have no effect?
Yes, you need to enable CORS on the server side. That is if you have control on the server.
Here are the Headers that should be returned from the server to enable CORS
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET,POST,PUT,DELETE
Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept
You can share some details about your server like if you want to add these headers from the code or in the WebServer itself.
Regarding the question about the reason why setting the headers in the POST request has no effect. The browser issues an OPTION request before your XHTTP request to ask the permission from the server about accepting CORS.
So, if you have control on the server, then you can add the headers I mentioned before. If not, then you can use some browser plugins to overcome this check.
Here is how the network tab in the developer tools should look like

Resources