Cross-Origin Request Blocked with React and Express - javascript

So I hit this error, when I was trying to send data to the back end using React. From what I learnt I need to allow the communication on the back-end and in the .htaccess file. Here are some of the links I used:
No 'Access-Control-Allow-Origin' - Node / Apache Port Issue
How does Access-Control-Allow-Origin header work?
Both of them have code, but it didn't help.
So far my Server-side code is this:
app.use(function (req, res, next) {
// Website you wish to allow to connect
// res.setHeader('Access-Control-Allow-Origin', 'http://localhost:3000');
res.setHeader('Access-Control-Allow-Origin', '*');
// Request methods you wish to allow
res.setHeader('Access-Control-Allow-Methods', 'POST');
// 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();
});
This is my Client-side code:
sendMail(e) {
e.preventDefault();
var name = document.getElementById('name').value;
var contactReason = document.getElementById('contactReason').value;
var email = document.getElementById('email').value;
var additionalInfo = document.getElementById('additionalInfo').value;
var body = {
name: name,
contactReason: contactReason,
email: email,
additionalInfo: additionalInfo,
};
console.log(JSON.stringify(body));
fetch('http://localhost:4000/', {
method: 'POST',
body: body,
}).then(r => console.log(r)).catch(e => console.log(e));
}
So what am I missing? I do not have an .htaccess file, but I'm doing it all locally so I'm not sure if I can even use it.
It looks to me like I'm allowing all I need, but I guess it's not enough.
If you're going to mark as a duplicate, please at least make sure my issues are covered by the answer.

There's a node package called cors which makes it very easy.
$npm install cors
const cors = require('cors')
app.use(cors())
You don't need any config to allow all.
See the Github repo for more info: https://github.com/expressjs/cors

One reason might be you're using the route as localhost:8000 rather than http://localhost:8000.
USE
http://localhost:8000
DON'T USE
localhost:8000

if you add this header
res.setHeader('Access-Control-Allow-Origin', '*');
you're using credential mode (means you're sending some authentication cookie from your app) and as for CORS specification you cannot use the wildcard * in this mode.
you should change your Access-Control-Allow-Origin header to match the specific host who generated the request
you can change this line:
res.header('Access-Control-Allow-Origin', '*');
to
res.header('Access-Control-Allow-Origin', 'the ip address');
but to be more generic, something like this should work:
res.setHeader('Access-Control-Allow-Origin', req.header('origin')
|| req.header('x-forwarded-host') || req.header('referer') || req.header('host'));
in addition you have even to allow OPTIONS requests from the browser otherwise you will get a preflight request error.
res.setHeader('Access-Control-Allow-Methods', 'POST, OPTIONS');

To anyone else that this may help, I was using axios with withCredentials: true.
On my Express backend, I was simply doing,
app.use(cors())
What fixed it was either removing withCredentials: true from the React frontend or changing my backend to,
app.use(cors({ credentials: true }))

you have to allow OPTIONS method as well
res.setHeader('Access-Control-Allow-Methods', 'POST, OPTIONS');
the browser send it with any post request to other domain to check how it will communicate with this remote server.

Related

How to set access control allow origin in socket io

I am using socket.io and express js. I want to set access control allow origin to the socket connection
I've tried setting the origins property when initializing socket
var io = require('socket.io')(http, {origins: 'http://www.example.com'})
In the image above access control allow origin is set to *. I want to set that to example.com (also note the request method is GET)
In this image however the access control allow origin header is set (also note the request method is POST)
How can I add the access control allow origin header when the request method is GET. Please help
Have you tried:
io.set('origins', 'http://yourdomain.com:80');
Or you can also try server.origins like below:
io.origins((origin, callback) => {
if (origin !== 'https://foo.example.com') {
return callback('origin not allowed', false);
}
callback(null, true);
});
By returning true, you allow the origin. Otherwise, send the error message. Refer docs here
please try below in express main file
// Add headers
app.use(function (req, res, next) {
// Website you wish to allow to connect
res.setHeader('Access-Control-Allow-Origin', 'http://yourdomain.com:80');
// Request methods you wish to allow
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
// Pass to next layer of middleware
next();
});
In Express you can use like this:
app.all('*(or set for what way you exectly need)', function (req, res, next) {
res.setHeader('Access-Control-Allow-Origin', 'http://www.example.com');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
res.setHeader('Access-Control-Allow-Headers', 'your headers');
next();
});
Also in the socket.io you do not need to specify separately headers for POST or GET... this is a different communication protocol.
Here is example for socket set you can try:
io.set( 'origins', '*www.example.com' );
Access-Control-Allow-Origin: http://example.com
Access-Control-Allow-Methods: GET
Access-Control-Allow-Headers: Content-Type

axios delete call returns 405

We are running a Tornado service in the background which accepts post and delete calls from the React application.
Our axios.post call works perfectly fine but it fails on our delete request with the following error message
405 (Method Not Allowed)
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:3000' is therefore not allowed access.
export const StopBuild = (action$) =>
action$.ofType(STOPBUILD)
.mergeMap((action) => {
return Observable.fromPromise(axios.delete(action.stopRequest))
.map(response => PlatformBuildSuccess(response))
.catch(error => Observable.of(PlatformBuildFailure(error, action.platform)))
})
From server side, this is what we have currently set,
self.set_header("Content-Type", "*")
self.set_header("Access-Control-Allow-Origin", "*")
self.set_header("Access-Control-Allow-Headers", "*")
self.set_header('Access-Control-Allow-Methods', 'POST, GET, OPTIONS, PUT, DELETE')
Something else we noticed that when on the server side we only set the following header POST call still works. I think we are going wrong on the server end.
self.set_header("Access-Control-Allow-Origin", "*")
Any help would be appreciated.
What you can do is, allow cors in your API request:
Like this :
axios.delete(url, { crossdomain: true }) // an example
you can take this as an example and add crossdomain:true in your delete request.
let me know if cors error still persists.
This is a CORS issue. As the error states it, the DELETE operation is not allowed yet. Here is explained that you have to add the DELETE method to the Access-Control-Allow-Methods response header of the preflight request.
On server side, using nodejs, allowing CORS would look like this:
const corsMiddleware = (req, res, next) => {
res.header('Access-Control-Allow-Origin', '*')
res.header('Access-Control-Allow-Headers', '*')
res.header('Access-Control-Allow-Methods', 'OPTIONS, POST, DELETE')
next()
}
app.use(corsMiddleware)
The request can be made from all origins with all headers, and OPTIONS, POST and DELETE methods are allowed.
For CORS request there is one package available called cors. You can try that by installing it as,
npm install cors --save
then you can require it and use that as middleware here the example,
const express = require('express');
const cors = require('cors');
const app = express();
app.use(cors());
More on cors npm package here

React: Axios Network Error

This is my first time using axios and I have encountered an error.
axios.get(
`http://someurl.com/page1?param1=1&param2=${param2_id}`
)
.then(function(response) {
alert();
})
.catch(function(error) {
console.log(error);
});
With the right url and parameters, when I check network requests I indeed get the right answer from my server, but when I open console I see that it didn't call the callback, but instead it caught an error.
Error: Network Error
Stack trace:
createError#http://localhost:3000/static/js/bundle.js:2188:15
handleError#http://localhost:3000/static/js/bundle.js:1717:14
If Creating an API Using NodeJS
Your Express app needs to use CORS (Cross-Origin Resource Sharing). Add the following to your server file:
// This should already be declared in your API file
var app = express();
// ADD THIS
var cors = require('cors');
app.use(cors());
For fuller understanding of CORS, please read the Mozilla Documentation on CORS.
my problem was about the url I was requesting to. I hadn't inserted http:// at the beginning of my url. I mean I was requesting to a url like 92.920.920.920/api/Token instead of http://92.920.920.920/api/Token. adding http:// solved my problem.
It happens when you work on localhost and forgot to add http://
Wrong Usage
const headers = {
"Content-Type": "application/json",
Authorization: apiKey,
};
const url = "localhost:5000/api/expenses/get-expenses";
axios.get(url, { headers });
// NETWORK ERROR
The correct one is
const headers = {
"Content-Type": "application/json",
Authorization: apiKey,
};
const url = "http://localhost:5000/api/expenses/get-expenses";
axios.get(url, { headers });
// WORKS FINE IF YOU HANDLED CORS CORRECTLY IN THE SERVER SIDE
In addition to #jacobhobson answer, I had also used some parameters to made it work.
app.use(cors({origin: true, credentials: true}));
I was having same issue on production on digital ocean droplet. I was using axios in ReactJS to call Node.js API.
Although I included cors
const cors = require('cors');
app.use(cors());
But I still had to add
res.header( "Access-Control-Allow-Origin" );
before calling out my controller. And it worked for me. There I realized that cors is not working properly. So I uninstalled and installed them again and It Works!
Complete code is here.
So either you use
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
res.header("Access-Control-Allow-Headers", "x-access-token, Origin, X-Requested-With, Content-Type, Accept");
next();
});
or use
app.use(cors());
It's the same.
I received a network error with axios 0.27.2 when I was trying to upload an image to our server. After I set headers like below no error is received.
headers:{"Accept":"application/json, text/plain, /","Content-Type": "multipart/form-data"}
and you need to check with your api request's body type in your collection like if it's form-data or x-wwww-form-urlencoded or ..etc.
Make sure you have the same port number in cors({ origin : [ "http://localhost:3001"]}) and the .env file.
In my case I used "https" instead of "http", check that too.
I just want to let you know that after searching for a solution for two days, I was able to solve my error.
Since the proxy was the source of the issue, I must configure a proxy in the package.json file, and I have to follow these instructions in the function that uses Axios:
try { await axios.post("user/login", formData).then((res) => { console.log(res.data); }); } catch (error) { console.log(error.response.data.message); }
and in package.json file need to add a proxy:
"proxy": "http://localhost:6000",
for better understand check this documentation: enter link description here
If you are running react native in development while using real device connected via USB(and the API server is being accessed via development machine IP), ensure the development machine and the device are both connected to the same network
This is happening because of restrict-origin-when-cross-origin policy.Browser sends a pre-flight request to know whom the API server wants to share the resources.
So you have to set origin there in API server and send some status.After that the browser allow to send the request to the API server.
Here is the code.I am running front-end on localhost:8000 and api server is running on port 6000.
const cors = require("cors");
app.options("*", cors({ origin: 'http://localhost:8000', optionsSuccessStatus: 200 }));
app.use(cors({ origin: "http://localhost:8000", optionsSuccessStatus: 200 }));
I have set origin as my front-end url, If You set it to true , then it will allow only port 8000 to access rosource, and front-end running on port 8000 can not access this resource. Use this middleware before route in api server.
I have resolved my issue by adding this header.
var data = new FormData();
data.append('request', 'CompaniesData');
var config = {
method: 'post',
url: baseUrl, headers:{"Accept":"application/json, text/plain, /","Content-Type": "multipart/form-data"},
data : data
};
axios(config)
.then(function (response) {
console.log(JSON.stringify(response.data));
})
.catch(function (error) {
console.log(error);
});
i'm using axios in react-native as android and .net as backend, i have same issue but i can't solve the problem. I think it is security problem when i type the url in chrome it warns me about that in emulator.
axios("http://10.0.2.2:5001/api/Users/getall")
.then((result) => setUsers(result.data.data))
.then((json) => {
return json.data;
})
.catch((error) => {
console.error(error);
})
.then((response) => response.parse());
In my case, I'm using Hapi.js as the backend, so all I had to do is set the cors value to true as in the code below;
const server = Hapi.server({
port: 4000,
host: 'localhost',
state: {
strictHeader: false
},
routes: {
cors: true
}
});
change the port number of your node server.
It took more than 3 hours to solve this error. Solution ended with changing port numer which was initially set to 6000, later set to 3001. Then it worked. My server localhost base url was:
"http://localhost:6000/data"
I changed port number in app.listen() on server and from frontend I call that GET route in async function as
await axios.get('http://localhost:3001/data').
It is working fine now.
If you face the address issue: address already in use :::#port
Then on command prompt: killall -9 node

Failed to fetch: Request requires preflight, which is disallowed to follow cross-origin redirect

I'm using Express for webserver, and using isomorphic-fetch module from client to using XHR.
I have three servers for my web application:
Port 3000 -> Admin Website
Port 3001 -> Public Website
Port 3002 -> API Server
API Server has resources named "skills" which has some data, and get it like this:
GET http://mydomain:3002/skills
it returns JSON data.
But when I request to 3002 from 3000/3001, it fails with this message:
Fetch API cannot load http://example.me:3002/skills. Redirect from 'http://example.me:3002/skills' to 'http://example.me:3002/skills/' has been blocked by CORS policy: Request requires preflight, which is disallowed to follow cross-origin redirect.
I don't get it why there is 'redirection' or something. This is my server side code, I granted all CORS related headers:
const express = require('express');
const app = express();
...
// CORS
app.use((req, res, next) => {
var allowedOrigins = ['http://example.me', 'http://example.me:3000', 'http://example.me:3001', 'http://example.me:3002'];
var origin = req.headers.origin;
if(allowedOrigins.indexOf(origin) > -1){
res.setHeader('Access-Control-Allow-Origin', origin);
}
res.setHeader('Access-Control-Allow-Credentials', true);
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,Content-Type');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS, HEAD');
if (req.method === "OPTIONS") {
return res.status(200).end();
}
next();
});
app.use(require('./routes'));
...
app.listen(3002, () => console.log(".API Server listening on port 3002..."));
And this is client side code that using Fetch API:
fetch('http://example.com:3002/skills', {
method: 'GET',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
credentials: 'include',
cache: 'no-store',
mode: 'cors'
})...
As you can see there is no redirection code. I spent almost a day to fix this issue, but everything I tried was all failed, every information that I found was useless.
I think splitting services to API Server and Web Server(actually returns HTML) was good idea, and want to go with this approach.
Is there a way to fix this problem? Any advice will very appreciate.
I solved this issue few years ago, still don't get it why it happened.
However my solution was simple, put every API into /api path.

Setting Access-Control-Allow-Origin doesn't work with AJAX/Node.js

I keep facing the same error over and over again:
XMLHttpRequest cannot load http://localhost:3000/form. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8000' is therefore not allowed access. The response had HTTP status code 404.
I've read countless posts similar to this one and they all pretty much have the same answer, namely to add the following setting: res.setHeader('Access-Control-Allow-Origin', '*').
That's what I've been doing but it still doesn't work.
I gave an angular.js app on localhost:8000 (when a btn is clicked logsth() is called) and my node works on localhost:3000. Here's what they look like:
app.controller('Contact', ['$scope', function($scope) {
$scope.logsth = function(){
var datas = {'may':'4','june':'17'};
$.ajax({
url: 'http://localhost:3000/form',
method: 'POST',
crossDomain: true,
data: datas
});
};
}]);
And my node:
var express = require('express');
var router = express.Router();
var app = express();
app.use(function (req, res, next) {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
res.setHeader('Access-Control-Allow-Credentials', true);
next();
});
app.post('/form', function(req, res){
console.log("e-mail sent");
res.send('yey');
});
module.exports = router;
Not too much code here but for now I'm only looking to get rid of the error.
EDIT: When I use app.use(...) and app.post(...) and go to localhost:3000/form I get 404 error. But when I use router.use(...) and router.post(...) at least the link works fine. Also, there is no 'allow-origin' error, but I do get: POST http://localhost:3000/form 404 (Not Found). However, when I go to http://localhost:3000/form it displays the response and console.log. Should I leave it as router instead of app?
Just leave this single line did the trick for me:
res.setHeader('Access-Control-Allow-Origin', '*');
Update:
You can try to install cors module from npm.
The issue is that you're returning a wildcard origin (*) and trying to pass credentials (res.setHeader('Access-Control-Allow-Credentials', true);). You cannot to both. If you must use Access-Control-Allow-Credentials, then you will need to be explicit about the allowed origins in your Access-Control-Allow-Origin header.
So, either remove this:
res.setHeader('Access-Control-Allow-Credentials', true);
Or change the origins to this:
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:3000');

Categories

Resources