Problem with CORS on React and PUT Ajax PUT request - reactjs

I have an issue with my app. I use Express/node for the API and try to access it with React which works fine with Axios.
now I tried a DevExpress grid component to display data. fetching data is working fine but if I want to edit and save I get always a CORS error.
My settings on express:
app.use(
cors({
origin: '*',
methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
})
);
The API looks like this:
router.put('/dataToEdit', auth, (req, res) => {
MasterData.updateData(req, res);
});
If I want to call and bind to the grid:
const dataSource = createStore({
key: 'helperboxTypeId',
loadUrl: `${url}/getAlldataToEdit`,
insertUrl: `${url}/dataToEdit`,
updateUrl: `${url}/dataToEdit`,
deleteUrl: `${url}/dataToEdit`,
onBeforeSend: (method, ajaxOptions) => {
ajaxOptions.headers = {
'Content-Type': 'application/json',
'x-auth-token': localStorage.token,
};
ajaxOptions.crossDomain = true;
},
});
I tried it I think with every possible constellation of settings and I'm searching for about 1 day in several forums before I asked this :)
maybe somebody is using the same component and can help somehow.
the error is:
Access to XMLHttpRequest at 'http://localhost:5000/api/masterData/dataToEdit' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Another solution could be that I use Axios there but was not able to integrate it.
Many thanks in advance!

You should allow Access-Control-Allow-Origin as following:
app.all('/*', function (req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "X-Requested-With");
next();
});

Finally i found it thanks for the eye opener comments :)
the problem was that i missed at the top of the backend server.js a line i added weeks ago...
app.get('/', (req, res) => res.send(text.SERVER_API_RUNNING));
and seems if i add the cors setting then it works only for a part of my API's.

Related

Cannot fetch from localhost with Authorization header

I'm having a hard time sending a get request to my expressjs backend with the fetch method.
fetch('http://localhost:9000', { method: 'GET', headers: { Authorization: `Bearer ${accessToken.accessToken}` }}).then(() => {
debugger
}).catch((error) => {
debugger
})
Based on what I could read, this seems correct - The request is however not reaching the API.
I tried constructing the options object like so, without any luck:
const options = {
method: "GET",
headers: headers
};
Without the headers, my request reaches the API. Anyway, the error that I'm getting is this:
error: TypeError: Failed to fetch
If you make that request from an origin other than http://localhost:9000, the Authorization header will cause the browser to make a CORS preflight request OPTIONS http://localhost:9000 before the GET request, and if that fails, the GET request would not be made.
You must ensure that your server handles the preflight, e.g., through the cors middleware.
So I found a solution, basically I added this middleware in my Express application to allow CORS,
app.use((req, res, next) => {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "*");
res.header("Access-Control-Allow-Methods", "*");
next();
});

To avoid the 'Access-Control-Allow-Origin' issue, how should CORS be set up on a MERN app that calls an API that is located somewhere else?

I am playing around with a MERN app that calls the themealdb api which works fine, until authentication and authorization with JWT and cookies are applied. If I log in, then whenever a call is made I get the following
Access to XMLHttpRequest at
'https://www.themealdb.com/api/json/v1/1/search.php?f=a' from origin
'http://localhost:3000' has been blocked by CORS policy: 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'. The
credentials mode of requests initiated by the XMLHttpRequest is
controlled by the withCredentials attribute.
It looks to me that the following line of code that is on the React side is to blame
axios.defaults.withCredentials = true;
If I comment this line out, the problem goes away and the calls are made without issue.
Looking around here through the answers it seems that the solution can be worked out on the backend which is Express for me, but so far nothing works.
The Express code had this for cors:
app.use(cors({origin: ['http://localhost:3000'], credentials: true}));
I replaced that with the following using both let and var for corsOptions in case but the same error:
let corsOptions = {
origin: 'http://localhost:3000',
credentials : true
}
app.use(cors(corsOptions));
app.use(function (req, res, next) {
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:3000');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
res.setHeader('Access-Control-Allow-Credentials', true);
next();
});
Any advice on what to do? For such a situation what needs to be added to the server side to make it work?
Thanks
I usually use this snippet to enable CORS for a pre-configured list of origins:
const allowOrigins = ['http://localhost:3000', /** other domains if any */ ]
const corsOptions = {
credentials: true,
origin: function(origin, callback) {
if (allowOrigins.indexOf(origin) !== -1) {
callback(null, true)
} else {
callback(new Error('Not allowed by CORS'))
}
}
}
server.use(cors(corsOptions));
Also, as per MDN, you can try setting the withCredentials option to false on your client.
Alternatively, if you are connecting to a service which you do not maintain, you can instead create a Node proxy which will call the 3rd party service instead of your client calling it directly.
const express = require('express')
const request = require('request')
const port = process.env.PORT || 8000
let server = express()
const proxyMiddleware = (req, res, next) => {
let url = `https://www.example.com/${req.url}`
let proxyRequest = request(url)
// Pass request to proxied request url
req.pipe(proxyRequest)
// Respond to the original request with the response from proxyRequest
proxyRequest.pipe(res)
}
server.use(proxyMiddleware)
server.listen(port, () => console.log(`Listening on ${port}`))

Fetch http://localhost:3001/ from Chrome Extension with React

I have seen some similar problems and solutions where people want to hit http://localhost:3001/some_url and use cors to do so.
But my problem is a little different. My web app is not a website but a web-extension.
SO far I cannot find a way to fetch from http://localhost:3001/url even with using cors.
What I have tried is:
Server:
const cors = require("cors");
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();
});
app.use(
cors({
origin: "http://localhost:3001/url" // restrict calls to those this address
})
);
In background.js file:
create(urls){
console.log(urls);
return new Promise((resolve, reject) =>{
fetch('https://cors-anywhere.herokuapp.com/'+'http://localhost:3001/url', {
method: 'POST',
body: JSON.stringify(urls),
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
"Access-Control-Allow-Origin: *"
}
})
.then(result => result.json())
.then(json => resolve(json))
.catch(err => {
console.log(err);
reject(err);
});
});
}
I have also added "proxy": "http://localhost:3001/url" in packages.json.
I am still getting the error:
Access to fetch at 'http://localhost:3001/url' from origin 'chrome-extension://extension_id' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: The 'Access-Control-Allow-Origin' header has a value 'http://localhost:3001/url' that is not equal to the supplied origin. Have the server send the header with a valid value, or, if an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
Is there any way to solve the issue?
It looks like you're adding a path /url to the origin, but an origin is:
Web content's origin is defined by the scheme (protocol), host
(domain), and port of the URL used to access it
Try using http://localhost:3001 as the origin value.

Can't connect to twilsoc

I am getting this bizarre twilsoc error when trying to connect to twilio through node and react. I cannot figure out how to fix this. This seems to be happening on the server side of my application. I have generated the token based on the instructions on the website.
index.js:1437 Error: Can't connect to twilsock
at Upstream.send (upstream.js:245)
at TwilsockClient.post (client.js:280)
at network.js:176
at Retrier.<anonymous> (network.js:114)
at Retrier.emit (events.js:136)
at Retrier.attempt (retrier.js:56)
at retrier.js:111
Here is on the front end
componentDidMount() {
fetch("http://localhost:3001/chat/token", {
headers: { 'Content-Type': 'application/x-www-form-urlencoded',
'Access-Control-Allow-Origin': "*",
'Access-Control-Allow-Headers': "*"
},
method: 'POST',
body: `identity=${encodeURIComponent(this.props.username)}`
})
.then(res => res.json())
.then(data => Chat.create(data.token))
.then(this.setupChatClient)
.catch(this.handleError);
}
here is the server
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(pino);
app.use(cors());
const sendTokenResponse = (token, res) => {
res.set('Content-Type', 'application/json');
res.send(
JSON.stringify({
token: token.toJwt()
})
);
};
app.get('/api/greeting', (req, res) => {
const name = req.query.name || 'World';
res.setHeader('Content-Type', 'application/json');
res.send(JSON.stringify({ greeting: `Hello ${name}!` }));
});
app.get('/chat/token', (req, res) => {
const identity = req.query.identity;
const token = chatToken(identity, config);
sendTokenResponse(token, res);
});
app.post('/chat/token', (req, res) => {
console.log('this is firing on the backend')
const identity = req.query.identity;
const token = new AccessToken('AC821b3924fcf9577a0eb017c4b21b----', "SK8c95cf6ba0e4a0ec5499d12ae4d----", "o4x7JC9xTEAsZC06SVsnfb2xZU9n----");
const chatGrant = new ChatGrant({
serviceSid:"ISdd3f2b55594f45038ac88d84b78e----" ,
});
token.addGrant(chatGrant);
token.identity = identity;
sendTokenResponse(token, res);
});
app.get('/video/token', (req, res) => {
const identity = req.query.identity;
const room = req.query.room;
const token = videoToken(identity, room, config);
sendTokenResponse(token, res);
});
app.post('/video/token', (req, res) => {
const identity = req.body.identity;
const room = req.body.room;
const token = videoToken(identity, room, config);
sendTokenResponse(token, res);
});
app.listen(3001, () =>
console.log('Express server is running on localhost:3001')
);
the latest versions of express are not using bodyparser.json any more, it's now a part of express, try using:
express(express.json())
instead of
express(bodyParser.json())
Twilio developer evangelist here.
This actually looks like my code 😄. This is good news, because it's from my post on how to proxy to an Express server with React so you can avoid CORS issues. If you are using my repo then you should be able to start both the server and the front end applications by running:
npm run dev
Then you don't need to fetch from an absolute URL, instead you can just use:
fetch("/chat/token", {
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
method: 'POST',
body: `identity=${encodeURIComponent(this.props.username)}`
});
And the webpack dev server will proxy the request through to the Express application.
Let me know if that helps at all.
Quick note on CORS
I noticed you're trying to pass the headers 'Access-Control-Allow-Origin': "*", 'Access-Control-Allow-Headers': "*" from your fetch request. However they are not request headers, but response headers. If you do need CORS headers then you need your Express server to return them as part of the response.
But as I said, the way I set up the code for this post should mean that you don't need CORS at all. So you shouldn't have to worry about this for now.
If you're using express, the easiest way to achieve this is using the cors module.
First, install it using the next code:
npm install cors
Next, put the cors middleware in the express app:
app.use(cors())
If you want to learn more, read the cors module docs https://www.npmjs.com/package/cors
If none of these solutions work (they didn't for me), here's something that might be helpful which made the error go away for me: https://stackoverflow.com/a/56671780/404541
I had this problem because I mispelled the SIDs I was using when getting the token through the rest API. I made sure the SIDs were correct and the error went away.

AngularJs $http GET passing custom header returns 404

I've been reading many blogs about it and I could not figure it out how to solve my problem..
I need to pass a token as a custom header to a get $http.. I get an error 404 because the GET request turns into OPTIONS.
The nodejs API Rest is working properly as I test it with the chrome "rest console" app.
Thank you Kasper..
This was my server code before starting this thread..
app.all('/*', function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", 'X-Requested-With, Content-Type');
res.header('Access-Control-Allow-Methods', 'GET, POST', 'DELETE', 'PUT');
next();
});
With this server code, everytime I send a request (GET) from the client with AngularJS adding a custom header "token"
myapp.factory("Booking", function ($resource) {
return $resource(
serverUrl + "/agp/pricelist",
{}, //default parameters
{
"reviews": {'method': 'GET', 'params': {'reviews_only': "true"}, isArray: true,
headers: {'Content-Type':'application/json', 'token': 'diego' }}
}
);
});
So, when you send a custom header rather than the followings:
Accept
Accept-Language
Content-Language
Last-Event-ID
Content-Type, but only if the value is one of:
application/x-www-form-urlencoded
multipart/form-data
text/plain
the type cors request is not "simple" anymore with a custom header, so when the client makes the request in fact it is making a pre-request with method "OPTIONS" first and then makes the "GET".. in between I was getting 404 error.
I added then to my server:
app.all('/*', function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", 'X-Requested-With, Content-Type, token');
res.header('Access-Control-Allow-Methods', 'GET, POST', 'DELETE', 'PUT', 'OPTIONS');
res.header('Access-Control-Request-Method', 'GET');
res.header('Access-Control-Request-Headers', 'token');
if ('OPTIONS' == req.method) {
res.send(200);
}
else {
next();
}
// next();
});
It was supposed to work with the access-control headers I added, but it was still sending back the 404 error.. So the work around was to add
if ('OPTIONS' == req.method) {
res.send(200);
}
else {
next();
}
Because as I said before, with a custom header the client first ask for permissions with OPTIONS method, and the sends the proper GET or whatever.
I did not find out another solution since this seems to be a work around, but at least I am not stuck anymore.
This is a good and practical link a about CORS
http://www.html5rocks.com/en/tutorials/cors/
Hope this helps someone.
King regards
I'm not too versed with CSRF and the likes, but I do believe this might be the issue I had with contacting my Express server with Angular.
http://mircozeiss.com/using-csrf-with-express-and-angular/
As stated in that article, Angular uses it's own X-XSRF-TOKEN for CSRF protection. Hence, you need to take that into account when setting up your server.
Following along with that guide and Express v3 all my requests going from the client side to the server side, magically started working.
If this is not the case (and I'm way out there), let me know.
What does your full serverside config look like?

Resources