I am trying to fetch an API on ReactJS with basic authentication (this is a complex request).
I have stumbled upon many articles, most are suggesting to modify something on the node but here, in this case, I am not using any node server. I have commented out all the NodeJS code and I am fetching this API directly from componentDidMount(), apparently, ReactJS has it's own backend server. I am using a third party cors chrome plugin for the time being, but I am averse towards using third party proxy servers like Heroku or NGINX or third party libs like axios. Cors chrome plugin helped me to resolve the access-control-allow-origin issue but it then raised this new issue.
Access to fetch at 'https://server-iam-fetching/' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.
I tried few things like appending access control checks on the header but none seems to work. Here is my sample code:
let headers = new Headers();
headers.append("Access-Control-Request-Headers", "*")
headers.append('Authorization','Basic ' + btoa(username + ":" + password));
credentials
allow requests
allow origins
..
..
etc
const someRequest = new Request(url, {
method: 'GET',
headers:headers,
mode:'cors',
cache: 'default'
});
componentDidMount(){
fetch(someRequest)
.then(response => response.json())
.then(json => console.log(json))
}
Feel free to comment for any questions. I am on MacOS. Also, I don't want to disable my chrome web security.
Actually, if you have access to the API you should fix it on your NGINX configuration or on backend codes. but if you have no access there are two recommended way:
Write a mapper proxy API by node/express and send all of your calls to it and the mapper API send it to the main API. in the mapper you have access allow all origins:
const express = require('express');
const request = require('request');
const app = express();
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', '*');
next();
});
app.get('/jokes/random', (req, res) => {
request(
{ url: 'https://the-main-api-address' },
(error, response, body) => {
if (error || response.statusCode !== 200) {
return res.status(500).json({ type: 'error', message: err.message });
}
res.json(JSON.parse(body));
}
)
});
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => console.log(`listening on ${PORT}`));
If you are using webpack-dev-server you can use below config to allow all origins on your webpack devServer:
devServer: {
...
headers: {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, PATCH, OPTIONS",
"Access-Control-Allow-Headers": "X-Requested-With, content-type, Authorization"
}
}
Or pass a proxy:
devServer: {
contentBase: DIST_FOLDER,
port: 8888,
// Send API requests on localhost to API server get around CORS.
proxy: {
'/api': {
target: {
host: "0.0.0.0",
protocol: 'http:',
port: 8080
},
pathRewrite: {
'^/api': ''
}
}
}
},
Hint: I prefer to use the first one.
This post is just for your development mode, you can launch an instance of Google Chrome that has not security modules and it won't send OPTION calls and definitely you won't see CORS error, so open your terminal and write the following commands in it:
open -n -a /Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --args --user-data-dir="/tmp/chrome_dev_test" --disable-web-security
Related
I have an express project set up on Heroku and a react front end set up on vercel.
When I make a request from the front end, I get the following error:
Access to fetch at 'https://helpr-dev.herokuapp.com/users/register' from origin 'https://helpr-front.vercel.app' 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 have CORS implemented on the Express app:
const cors = require('cors')
app.use(cors())
And I've also tried passing it a config like:
const whitelist = ['http://localhost:3000', 'https://helpr-front.vercel.app/']
const corsOptions = {
origin: function (origin, callback) {
if (!origin || whitelist.indexOf(origin) !== -1) callback(null, true)
else callback(new Error('Not allowed by CORS'))
},
credentials: true,
}
app.use(cors(corsOptions))
This is how a request looks like in the react app:
const submitRegisterForm = async e => {
e.preventDefault()
const response = await fetch(`${serverUrl}/users/register`, {
method: 'POST',
mode: 'cors',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: name,
email: email,
password: password,
accountType: accountType
})
})
const data = await response.json()
}
I've tried removing the mode: 'cors' part but it doesn't make a difference.
Can someone tell me what I'm missing here?
Front end app is hosted here: https://helpr-front.vercel.app/
Back end app is hosted here: https://helpr-dev.herokuapp.com/
Front end full code can be found here: https://github.com/coccagerman/helpr-front
Back end full code can be found here: https://github.com/coccagerman/helpr-back
Thank you!
So this was caused mainly by a problem with the connection to mongoDb atlas.
First, the Heroku IP adress wasn't whitelisted on the the database network connection. Fixed it like mentioned here: Connecting Heroku App to Atlas MongoDB Cloud service
Then I had an error on the mongo atlas connection URI I was using.
And lastly, It seems necessary to add the mode: 'cors', config on every request I make.
On express, no cors config is needed. I just use app.use(cors())
Adding to the database shows the error. what should I do?
Access to fetch at 'http:xxx' 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.
my function:
addItem = (e) => {
e.preventDefault();
const ob = {
X: 53.0331258,
Y: 18.7155611,
}
fetch("http://xxx", {
method: "post",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(ob)
})
.then(res => res.json())
.then(res => {
console.log(res);
})
}
try using ''no-cors' mode.
fetch('http://localhost:8080/example', {
mode: 'no-cors',
method: "post",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(ob)
})
Your server should respond with a response that looks like below
Access-Control-Allow-Origin: https://localhost:3000
Untill you are able to configure that as a workaround you can install the below chrome extension to resume your testing
https://chrome.google.com/webstore/detail/who-cors/hnlimanpjeeomjnpdglldcnpkppmndbp?hl=en-GB
But the above is only a workaround to continue development
I would suggest you read this article for understanding CORS
https://javascript.info/fetch-crossorigin
You must install cors.
npm install cors
inside the main scripts index.js or app.js
const cors = require("cors");
app.use(cors());
I resolved the issue by installing the cors node module and adding this on the requested server
const cors = require("cors");
app.use(cors());
For browser CORS is enabled by default and you need to tell the Browser it's ok for send a request to server that not served your client-side app ( static files ).
if you use RestFul API with node and express add this middleware to your file
app.use((req, res, next) => {
res.header("Access-Control-Allow-Origin", "*")
})
Try using the following code:
var corsOptions = {
origin: "http://localhost:3000"
};
app.use(cors(corsOptions));
You should copy in server.js(or app.js)
(I've experienced the exact same problem as this one. I was able to solve the problem by adding the following code to server.js.)
The middleware should be like this.
app.use((req, res, next) => {
res.header({"Access-Control-Allow-Origin": "*"});
next();
})
const cors = require("cors"); app.use(cors());
i use this but can't solve this problem.
app.use((req, res, next) => { res.header({"Access-Control-Allow-Origin": "*"}); next(); }) when use this code than solve this problem
try to add annotation #CrossOrigin , its worked for me .
#RestController #RequestMapping(value="") #CrossOrigin
In WordPress version 6 I solved the issue by using the mode option available in fetch api here
apiFetch( { mode: 'no-cors', url: 'https://api.example.com/?q=' + attributes.search_string } ).then( ( posts ) => {
console.log( posts );
} );
Actually it's more efficient to fix this bug from the server side like this:
npm install cors
inside the post operation:
app.post("/...", (req, res) =>{
res.set('Access-Control-Allow-Origin', '*');
//whatever you want here
}
you can read this article https://www.stackhawk.com/blog/react-cors-guide-what-it-is-and-how-to-enable-it/#enable-cors-on-server-side
OR you can easily convert the client side to work on the same domain with the server side by adding in the package.json (client side)"proxy" of the server domain like this:
"proxy": "http://xxxx/"
in this case you don't have to add the domain name in each request anymore.
and the last solution "it's not recommended" by adding {"mode": "no-cors"} to your request.
make a new variable called header:
const header = new Headers({ "Access-Control-Allow-Origin": "*" });
pass this variable as an object in fetch:
fetch(url, { header: header })
.then((res) => res.json())
.then((data) => console.log(data));
This will resolve the issue
I'm trying to make a call to my API on Jazz using Vue.js and Axios, but I am getting the following error:
Access to XMLHttpRequest at 'https://jazz.api.com/api/extra_stuff
_here' from origin 'http://localhost' 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.
I've been looking at other solutions like https://enable-cors.org/server_expressjs.html or adding
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "OPTIONS",
"Access-Control-Allow-Headers": "Content-Type, Authorization",
"Access-Control-Allow-Credentials": "true"
to my code and it still didn't work. Even if I do the wildcard for the Access-Control-Allow-Origin, I still get the CORS issue and cannot call my API. I am using Vue and Typescript for the client side and managed to get Express working for my server side. Here is a code snippet of my Axios API call:
return Axios.post('https://jazz.api.com/api/extra_stuff_here', context.getters.getRequest,
{
headers: {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "OPTIONS",
"Access-Control-Allow-Headers": "Content-Type, Authorization",
"Access-Control-Allow-Credentials": "true"
}
}
)
This is where I am calling my API in this TypeScript file and here is my server.js:
var express = require('express');
var path = require('path');
var cors = require('cors');
var bodyParser = require('body-parser');
var morgan = require('morgan');
var app = express();
app.use(morgan('dev'));
app.use(cors());
app.use(bodyParser.json());
var publicRoot = './dist';
//app.use(express.static(path.join(__dirname, '/dist')));
app.use(express.static(publicRoot));
app.get('/', function (req, res) {
res.sendFile("index.html", { root: publicRoot });
});
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Authorization");
res.header("Content-Type", "application/json");
res.header("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
res.header("Access-Control-Allow-Credentials", "true");
next();
});
app.listen(process.env.PORT || 80, function() {
console.log("listening on port 80");
});
No matter what I seem to do, I cannot figure out this CORS issue. Before I added express to my application, I still got the same issue, thinking that maybe express on the server side would fix the CORS issue. However it didn't help. Beforehand, I was running my Vue application by doing npm run serve. But any help would be great! Could it possibility be an issue with Jazz?
You’ve added the cors middleware but haven’t enabled it for OPTIONS requests
app.options('*', cors())
Try adding something like this to your server to enable it.
You can read further in the express docs here
https://expressjs.com/en/resources/middleware/cors.html
Update: I didn't manage to fix the CORS issue with Axios, but I did manage to find a workaround for this. Instead of using the Axios library, I am using fetch to call the API. Since all I need to do with my request call is to pass in parameters and get back data based on the parameters, my application works with fetch. While I was doing my research, I saw that there may be issues or limitations using fetch? But hey, it works for me so I'll be sticking with this solution. Here is my code as reference for anyone:
return fetch('https://dev.jazz.com/api/stuff_goes_here', {
method: 'post',
body: JSON.stringify(<request object goes here>)
}).then((res) => res.json())
.then((data) => {
return data;
}).catch((err)=>console.log(err))
This is my first time using axios and I have encountered an error.
axios.get(
`http://someurl.com/page1?param1=1¶m2=${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
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.