React node express app - Heroku CORS error - javascript

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())

Related

How do I Submit data from a vuejs form to zapier webhook using axios?

I am using vuejs / axios and I want to post data to a zapier webhook.
I've tried a number of things. However I continually get the following error:
Access to XMLHttpRequest at 'https://hooks.zapier.com/hooks/catch/7349379/owviy9/' from origin 'http://localhost:8080' has been blocked by CORS policy: Request header field content-type is not allowed by Access-Control-Allow-Headers in preflight response.
Here is my code:
submit(){
axios
.post(
'https://hooks.zapier.com/hooks/catch/7349379/owviy9j/',
this.formData,
{headers: {"Accept": "application/json"}}
)
.then(function(response) {
console.log(response);
});
}
I've also tried this but can't seem to get it to work:
var data = this.formData
axios.create({ transformRequest: [(data, _headers) => JSON.stringify(data)] })
.post('https://hooks.zapier.com/hooks/catch/7349379/owviy9j/', data)
}
How do I resolve this CORS issue?
From your first example just remove:
{headers: {"Accept": "application/json"}}
Zapier dosn`t allow headers to be sent.
Complete example:
const res = await this.$axios.post('https://hooks.zapier.com/hooks/catch/xxx/xxx/',
JSON.stringify(data)
)
When you try to make requests from the same machine but with different ports. Example: Your front end is running on port 3000, while your nodejs app is running on port: 8080. For security concerns the browser doesn't let you make the api requests.
Solution: Add Cors to your NodeJs App.
npm install cors
const cors = require('cors')
const app = express();
just add a line below this: app.use(cors()); //use it as a middleware and this will resolve your issue.

How to read custom header in CORS middleware

I have created CORS middleware using CORS package. This middleware will be called before each call. Here is my implementation.
const corsMiddleware = async (req, callback) => {
const { userid } = req.headers|| req.cookies {};
let whiteList = await getWhiteListDomains(userid)
return callback(null, {
origin: whiteList,
credentials: true,
allowedHeaders: ["userid", "authorization", "content-type"]
});
};
And added this middleware before route initialization as
app.use(cors(corsMiddleware));
app.options("*", cors(corsMiddleware));
app.get("/user", (req, res, next)=>{
// code
})
From Browser I am trying to call the API as
axios({ method: "get", url: "http://localhost:3000/user", headers: {userId:"1234"} });
While debugging on the server I see
access-control-request-headers:"userid"
in the headers of the request object.
I am not able to read the custom header. This might be happening because I am trying to read the custom header before CORS initialization. But still, I want to read that custom header.
You have mainly two problems in your code.
First one, and easier to solve is that you are missing access-control-allow-origin in the option that sets the Access-Control-Allow-Headers:
return callback(null, {
origin: whiteList,
credentials: true,
allowedHeaders: [
"access-control-allow-origin",
"authorization",
"content-type",
"userid"
]
});
The second one is the most important because it is related to how CORS works.
This problem you are having is that CORS is already rejecting the petition in the pre-flight OPTIONS request. It never allows the browser to execute the GET request.
You say that you want to read the custom header userId in the pre-flight OPTIONS request but you can't. The reason is because the pre-flight OPTIONS request is created by the browser automatically and it won't use the custom headers you are setting up in the Axios call. It will only send these headers for the CORS:
Origin // URL that makes the request
Access-Control-Request-Method // Method of the request is going to be executed
Access-Control-Request-Headers // Headers allowed in the request to be executed
Because your custom header is not being sent so in the pre-flight OPTIONS when you try to access the value of userId, you get an undefined value:
const { userid } = req.headers|| req.cookies;
console.log(userid); // undefined
And because you are using that value that is not matching in your async function getWhiteListDomains probably getting another undefined, the value set up in the origin option of the CORS middleware is undefined that provokes the CORS middleware rejects the pre-flight OPTIONS request.
let whiteList = await getWhiteListDomains(userid); // userid === undefined
console.log(whitelist); // undefined
return callback(null, {
origin: whiteList, // undefined
credentials: true,
allowedHeaders: ["userid", "authorization", "content-type"]
});
I am not totally sure which is your goal trying to use your custom header as CORS check, but my advise would be when dealing with customised CORS configuration to only check the Origin header because that's its purpose: to limit and control which URLs can access to your server and resources.
If you are interested in creating any kind of authorisation or limited by user implementation in the requests received by your server, I suggest you to use a different custom middleware and not involve CORS at all like you are trying now.
you must parse your request
try this
npm i body-parser
and
const bodyParser = require('body-parser');
app.use(bodyParser.json())

Access to fetch at from origin 'http://localhost:3000' has been blocked by CORS policy

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

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.

Categories

Resources