Firebase CORS issue - reactjs

I built a react app and I have deployed it on firebase. I have been getting this error whenever user searches.
Failed to load https://food2fork.com/api/search?key=0882376145a8bcae6c3cee&q=fish&count=50: Redirect from
'https://food2fork.com/api/search?key=0882376145a8107c5946c3cee&q=fish&count=50' to
'https://www.food2fork.com/api/search
key=0882376145a8bcae390107c5946c3cee&q=fish&count=50'
has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is
present on the requested resource. Origin 'https://recipe-finder-26e0e.firebaseapp.com' is therefore not allowed access.
As I am new to this one, I am unable to figure out how to enable CORS in firebase which I think is the problem. If anyone can tell me how to enable CORS I would be grateful Thank you.
Edit: Source code link --> https://github.com/AdiBev/Recipe-Finder
Update: I didn't understand in the beginning that CORS needs to be handled by back end. Thanks to #Ben. Ayoub for explaining it to me.
If it helps for any others like me who got same problem I found a great article and some proxies are mentioned there.
link ---> https://gist.github.com/jesperorb/6ca596217c8dfba237744966c2b5ab1e

In addition to Ben. Ayoub's solution it could be worth you looking into HTTPS Callable functions if it's only your app trying to communicate with the Function and it's not part of a wider external API.
They work similar to HTTPS endpoints but get rid of the headaches of CORS.
import * as functions from 'firebase-functions';
export const listener = functions.https.onCall((data, context) => {
if (data) {
throw new functions.https.HttpsError('invalid-argument');
}
return {
some: 'json',
};
}
You don't need to use the request and response parameters like in the HTTP Endpoint Cloud Function.
It accepts JSON as it's context and returns a simple JSON object.
Edit
To answer your original question, the cloud functions can make use of CORS
import * as functions from 'firebase-functions';
const cors = require('cors')({ origin: true });
export const listener = functions.https.onRequest((req, res) => {
cors(req, res, () => {
return;
});
// cloud function logic
res.json({ some: 'json' });
});

Related

Cors issue i also set the proxy in pkg.json due to cors and set the api according to it but this error is not remove

GET http://localhost:3000/api/fetch?search=12312321 404 (Not Found)
cors issue in Reactjs and node js
i use the proxy method in Reactjs but can't get rid from it please help me
proxy
"proxy":"http://localhost:5000/"
tried both
"proxy":"http://localhost:5000"
express
RegisterRoute.route('/fetch/:id').get( ( req , res) =>
{
console.log("called by someone ",req.params.id);
res.send("okey will");
});
Reactjs function which will call the backend api
FetchNotification(){
axios({
'method':'GET',
'url':'api/fetch',
'headers': {
'content-type':'application/octet-stream',
'x-rapidapi-host':'example.com',
'x-rapidapi-key': process.env.RAPIDAPI_KEY
}
,
'params': {
'id':'12312321'
},
})
}
when i simply call axios.get it perfectly work but when i give params to it it gives the error xhr:178 404 not found
a simple server which also returns the same result
const express = require('express');
const cors= require('cors');
const app= express();
var bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({ extended: false }));
// parse application/json
app.use(bodyParser.json());
app.use('*',cors());
app.get('/fetch/:id',(req , res) => {
console.log("calling",req.params.id);
});
app.listen(5000);
I can see that you're using Nodejs as server side. So, you can try changing following line
app.use('*',cors());
to
app.use(cors());
If this doesn't solve the issue, you can try adding a google chrome extension for CORS (Most probably). In this way, you'll not need any proxies being set for running servers.
Also, you need to do a small change in URL, instead of calling
'url':'api/fetch'
you need to provide an id in your call, because the backend api is accepting a parameter
'url':'api/fetch/some_id'
I feel there are multiple issues. I'll try to address them one by one.
Firstly, if you are proxying your requests correctly (which I think you are as per your package.json), then you'd not require the cors package. So you can get rid of that package.
Read more about why you shouldn't let all incoming request bypass the CORS check from security point of view -> Is it safe to enable CORS to * for a public and readonly webservice?
Now secondly, the url which you've specified on the frontend is 'url':'api/fetch', which means browser will make a call to http://localhost:3000/api/fetch?search=12312321 which it correctly did as seen in your error statement for 404.
Specifying the proxy as "proxy":"http://localhost:5000" in package.json means that now you are making requests to http://localhost:5000 instead of http://localhost:3000, but the browser would still think its http://localhost:3000. That's the whole purpose of proxying and how you kinda fool browser to do CORS without throwing any error.
But because on your server, you are listening to app.get('/fetch/:id',(req , res) instead of app.get('api/fetch/:id',(req , res), it doesn't matches with this URL as you have not explicitly handled requests starting with /api in some separate router module either.
So you should either update the url in the axios call to url':'/fetch while the proxy value in package.json is "proxy":"http://localhost:5000" or url':'fetch and "proxy":"http://localhost:5000/" respectively. Notice how i've used the /
OR
You can update the URL on the express end to app.get('api/fetch/:id',(req , res)
Lastly, whenever you receive a request, you need to return some value(string or JSON or even status code) as result.
In your case, you've simply console.log("calling",req.params.id); and didn't send back any response to the UI.
So even if your 404 would resolve after fixing the URL, you'd bump into request timeout error (408) as your UI will keep waiting for a response from the server while you didn't send any.
So you should do something like this maybe:
app.get('api/fetch/:id',(req , res) => {
console.log("calling",req.params.id);
res.send("It worked");
});
Notice how there's a response being sent back -> https://expressjs.com/en/starter/hello-world.html
If you don't want to send back a response, then you can simply return status like 200, 504 etc.
if you apply below code in backend/server i thing it will debug.
app.get('api/fetch/:id',(req , res) => {
console.log("calling",req.params.id);
res.send("It worked");
});

Here Maps Geocode API leads to Cross-Origin error

I use the first example here in order to get the geo coordinates based on an address:
https://developer.here.com/documentation/maps/3.1.15.1/dev_guide/topics/geocoding.html
My JavaScript coding looks almost the same as in the official documentation:
var platform = new H.service.Platform({
'apikey': 'HERE IS MY API KEY'
});
// Get an instance of the geocoding service:
var service = platform.getSearchService();
service.geocode({
q: 'Berlin'
}, (result) => {
result.items.forEach((item) => {
console.log("test");
});
}, alert);
However, when the geocode request is sent, I get the following error:
Access to XMLHttpRequest at '**https://geocode.search.hereapi.com/v1/geocode?xnlp=CL_JSMv3.1.16.1&apikey=[HERE IS MY API KEY]&q=Berlin**' from origin 'null' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
The API key is sent correctly, why do I still get the CORS error?
If I enter the request URL manually in the browser, I get a response and everything is fine.
Yes, the server will help with the issue. I'm here to suggest the alternative.
You can do the geocoding with the HERE Maps REST as well see docs — https://developer.here.com/documentation/geocoding-search-api/dev_guide/topics/endpoint-geocode-brief.html.
Since not all the browsers historically support the CORS (learn more about the CORS — https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) there is an approach, called JSONP. See some JSONP explanation Here Maps related in the old docs https://developer.here.com/documentation/places/dev_guide/topics/request-cross-domain-js.html.
Eventually the https://www.npmjs.com/package/jsonp npm package could be a good follow up and we can get something like this after installing the package (npm install jsonp --save).
import jsonp from 'jsonp';
jsonp('https://geocode.search.hereapi.com/v1/geocode?q=5+Rue+Daunou%2C+75000+Paris%2C+France&apiKey=my-api-key',
null,
(err, data) => {
if (err) {
console.error(err.message);
} else {
console.log(data);
}
});
This works great from my experience.
If you are testing this code by opening the file in the browser, you may get this error. I suggest using a local server for testing.

Access to XMLHttpRequest blocked by CORS Policy in ReactJS using Axios

I'm setting up stripe connect button in my React Component using Axios. I keep getting this error after redirection
Access to XMLHttpRequest at 'https://connect.stripe.com/oauth/token' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: Redirect is not allowed for a preflight request.
Thankyou.js:40 Error: Network Error
at createError (createError.js:16)
at XMLHttpRequest.handleError (xhr.js:87)
I get the code from the url and create a curl request using axios.Post. This is the code in my redirect URL
// Thankyou.js
export default class Thankyou extends Component {
constructor(props) {
super(props);
}
componentDidMount() {
const code = qs.parse(this.props.location.search, {
ignoreQueryPrefix: true
}).code;
const params = {
client_id: "*******************",
client_secret: "**********************",
grant_type: "authorization_code",
code: code
};
axios
.post(
"https://connect.stripe.com/oauth/token",
// apiBaseUrl,
{ params }
)
.then(function(response) {
console.log(response);
})
.catch(function(error) {
console.log(error);
});
console.log(code);
}
render() {
return (
<div>
<h2>Thank you for connecting with us!</h2>
</div>
);
}
}
There is nothing wrong with your code, but most likely the API endpoint the code trying to reach is not setup for JavaScript web app. CORS policy is set on the server-side and enforced primarily on the browser-side.
The best way to work around is to use Stripe's JavaScript solution such as Strip React Elements or Stripe.js.
A hacky way to get around CORS would be setting up Reverse proxy with solutions such as NGINX. For example, you can use the following nginx configuration:
server {
listen 8080;
server_name _;
location / {
proxy_pass http://your-web-app:2020/;
}
location /stripe/ {
proxy_pass https://connect.stripe.com/;
}
}
By doing so, all the API calls to Stripe.com could be through /stripe under your web app's URL. For example, calling http://yourapp/stripe/oauth/token would be same as calling https://connect.stripe.com/oauth/token
That being said, the second solution is hacky and Stripe may decide to block your reverse proxy server.
basically you need to talk to whoever is hosting this https://connect.stripe.com/oauth/token to enable CORS (Cross Origin Resource Sharing )
It is a security measure implemented by most standard browsers to stop unwanted requests to your backend
It's probably because Stripe doesn't provide JavaScript client so you either have to use your own server proxy or use something like "https://cors-anywhere.herokuapp.com/https://connect.stripe.com/oauth/token"
I hope this answer would be useful to new users:
This issue can be easily fixed by using an annotation in your spring boot rest controller class.
Something like below (also ref screenshot):
#CrossOrigin(origins = "http://localhost:4200")
Explicitly mention the react JS server URL that is causing this issue.
Now after adding above annotation (with your react JS server URL) the browser will allow the flow.
All the best.
Learn about CORS
Think about it, there is anything wrong with your axios.post request, it's successfully contacting the server. But there is one more thing to do before the server let you execute or manipulate it's files.
For security reasons, browsers restrict cross-origin HTTP requests initiated from within scripts. For example, XMLHttpRequest and the Fetch API follow the same-origin policy.
So your cross-origin request and the server Cross-Origin Resource Sharing (CORS) have to match.
How do you solve it?
Depending on your server and the server side programming language your are implementing, you can configure the different parameters to handle your CORS.
For example, you can configure that the only allowed methods will be:
GET HEAD
So if someone try to axios.post to your server with a different method like POST, it will return an error like this:
Access to XMLHttpRequest at 'https://connect.stripe.com/oauth/token' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: Redirect is not allowed for a preflight request.
Thankyou.js:40 Error: Network Error
at createError (createError.js:16)
at XMLHttpRequest.handleError (xhr.js:87)
Resources:
https://www.w3.org/TR/cors/
https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy
https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
I would suggest reading through this site: https://stripe.com/docs/recipes/elements-react
It gives specific instructions straight from stripe on using their API with react. Good luck!

CORs issue in axios using React

So I've researched the web and tried almost all the solutions on their for this issue I am having with CORs using yelps fusion API. I'm using react but trying to call this API with axios. Here is my code.
static YelpApiSearch(searchedCity, onSuccess, onError) {
const config = {
Authorization: process.env.REACT_APP_KEY
Origin: "https://vendors.test"
};
axios.defaults.headers.common["X-Requested-With"] = "XMLHttpRequest";
axios
.get(`https://corsanywhere.herokuapp.com/https://api.yelp.com/v3/businesses/search?categories=foodtrucks&location=${searchedCity}`,
{
withCredentials: true,
headers: config
}
)
.then(onSuccess)
.catch(onError); }
Refused to set unsafe header origin error
Any help would be appreciated. Thanks!
This isn't a CORS problem per se. The error message tells you what the problem is.
Refused to set unsafe header origin error
You can't specify the Origin header. It is determined by the browser. If you could specify it, it would break a large part of CORS's security.
Remove your attempt to specify it from the config object.

Webpack not accepting POST requests

I'm currently working on an Angular 2 web application which communicates with an API. In the application the user is able to choose a payment option and the API will return the url to the payment service.
The problem is that the payment service uses POST to go to the confirmation page which WebPack does not accept (for some reason it only allows GET requests) and we get the following error:
Cannot POST /selection/payment-method
Does anybody know how we could configure that WebPack allows POST requests also? I've contacted the payment provider but it is not possible to do a GET request instead of POST.
Thanks
Based on #Sven's answer, modification to the setup so that it works for POST all throughout
Add dependencies on body-parser, sync-request and add require dependencies on both in your webpack.config.js
var bodyParser = require('body-parser');
var request = require('sync-request');
In devServer part of webpack.config.js
devServer: {
setup: function(app) {
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: true
}));
app.post(/^\/(URL1|URL2|URL3)\//, function(req, res) {
var serviceCallResponse = request('POST', 'your app server url here' + req.originalUrl, {
json:req.body
});
res.send(serviceCallResponse.getBody('utf8'));
});
},
proxy: {
'*/other URLs proxy/*': 'your app server url here'
}
}
Change URL1/2 to the URLs you want to proxy and you place your app servers address.
This will work for all sorts of POST request proxy (working on json payload)
A hackish way to at least not get 404 errors is to proxy requests to /selection/payment-method and send back an empty response (or whatever content you want, I think that res is an instance of Express's Response class) for those, by adding the following to webpack.config.js:
devServer: {
proxy: {
'/selection/payment-method': {
bypass : (req, res) => res.end()
}
}
}
Documentation here.
Thanks to #robertklep who send me the link to the proxy documentation we found a way to deal with it. What we needed to do was instead of handling the POST request we needed to transform it someway into a GET. After reading some more of the documentation we came across the setup: property for your webpack-dev-server configuration.
With the setup: property you get the expressjs object and you are able to catch urls before it hits the route that says Cannot POST /url/to/page.
We ended up with this:
devServer: {
setup: function(app) {
app.post('/selection/payment-method', function(req, res) {
res.redirect('/selection/payment-method');
});
},
}
This way we got a GET request instead of POST and our application does an API request to check if the payment succeeded or not.
This is only used in development!
The Webpack-dev-server is only intended as your front-end server only, eg. to serve your static assets. Therefore only GET requests are supported.
If you would want to use a proxy or backend server, then you should implement this. You can use Express for this.
See how you can setup basic routing.

Resources