CORS issue performing api calls in react/redux application - javascript

I was trying to implement a mailchimp api and came across a cross domain issue with an error in chrome like this:
XMLHttpRequest cannot load https://us9.api.mailchimp.com/3.0/members.
Response to preflight request doesn't pass access control check: No
'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'http://example.com' is therefore not allowed
access. The response had HTTP status code 501.
After some research it turns out that api calls I make are made from the browser (I simply call api from one of my actions), but to fix this issue they need to be made on the server.
Hence I am trying to figure out a way to call an api from the server inside of my action, to bypass this issue.
EDIT:
One of the solutions I found is to use jsonp for this, however I had to drop it as well, as I can't authenticate with it.

The solution I found is to proxy api calls through express in the following way:
In your express config:
import request from 'request'
app.use('/api', function (req, res) {
let url = 'your_api_url' + req.url
req.pipe(request(url)).pipe(res)
})
What this allows you to do is instead of calling https://myapi.com/endpoint in your components is to use /api/endpoint this way express will replace all instances of /api on your server with your api url and perform an api call from the server itself.

Related

API request blocked by CORS

I'm trying to use the g-trends API in my vuejs application running from localhost, but keep running into issues of my requests getting blocked due to CORS restrictions: No 'Access-Control-Allow-Origin' header is present on the requested resource.
I know how to fix the issue when performing a fetch request, but not in a scenario where I don't actually see the request URL like when using an API. Is there a way to fix this?
const { ExploreTrendRequest } = require('g-trends');
const explorer = new ExploreTrendRequest();
explorer.past5Years()
.addKeyword("keyword")
.download().then(csv => {
console.log(csv)
})
I usually use a proxy server for avoiding this situation, your app asks your server to do that request for you so the communication with the API is managed by your server, when your server receives the answer it forwards it to your app and there won´t be any CORS problem.

CORS policy: No 'Access-Control-Allow-Origin' / 500 (Internal Server Error) Problem

Basically, I'm trying to get a username by id from Sequelize. The problem is that I am either stuck with a CORS problem or 500 Internal Server error depending on the response(status)
cors and 500
controller code
async getUserFromUserId (req, res) {
try {
// const user = await User.findByPk(req.body.id)
const id = req.body.id
const user = await User.findByPk(id)
res.send(user.username)
} catch (err) {
// or res.status(some random number).send() for CORS problem to appear
res.status(500).send({
error: 'an error has occured trying to fetch the users id'
})
}
},
client code
this.notifiedUser = (await UserService.getUserFromUserId({id: UserId})).data
I get a Status: 200 OK from postman though.
Postman Solution
Edit:
I have seen how the other Solution for the cors thingy, but the solutions does not specify as to why I get "undefined" results after resolving the cors problem.
So, CORS is actually really obnoxious in this regard, but there's a fairly straightforward way to fix this. It's a super useful security feature, though it is frustrating at best sometimes.
Your browser does what is called a Preflight Request, which is of the http verb OPTIONS. Your browser calls whatever route you want, but instead of what you asked it to do, it calls using OPTIONS first. Your server should accept all routes that the client can ask for with the OPTIONS method, and your server should respond with the following headers to be an externally available, cross-origin API.
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, ...
(note, you should not put the ... in, but you can put any HTTP verb in this list)
If you require your own headers (for auth purposes), you want to add this header for Client -> Server.
Access-Control-Allow-Headers: YourHeader, YourHeader2, YourHeader3
You want to add this one for Server -> Client
Access-Control-Expose-Headers: YourHeader,YourHeader3
Note that the OPTIONS call is an entirely separate call that you should handle as well as the GET method.
You've now told the browser what it is allowed to ask for, and what it can expect to get back from your API. If you don't respond to the OPTIONS request, the browser terminates the request, resulting in a CORS error.
I'm going to take a gander at a guess and assume you're likely using Express, which this answer describes how to set the headers on.
What do the headers mean, in English?
Access-Control-Allow-Origin
From where are clients allowed to access this resource (endpoint)? This can match partial domains with wildcards, or just a * to allow anywhere.
Access-Control-Allow-Methods
What HTTP methods are permissible on this route?
Access-Control-Expose-Headers
When I get a response from the server, what should I (the browser) expose to the client-side?
Access-Control-Allow-Headers
What am I as the client side allowed to send as headers?
Okay, so I figured out the problem.
In a way, I did not have to deal with any of the cors stuff because I believe that was not the main source of the problem.
So, instead of accessing my database data through "GET" and getting the data by doing this:
this.data = (Service.function(bodyValue)).data
I did "POST" to get the data, and accessed the data by simply doing this
const response = Service.function({
id: bodyValue
})
this.data = response.data
This accesses the data without having to get "secured" information from the database, but by accessing the data from the database by getting Observer object info from the database.
The Observer object looks as follows, which treats the user data as an object instead of pure data.
Compared to a data object, where each data {...} has user information.
I am not sure if I am using the correct words, but these are to the extent of my current understanding.
If your origin is from localhost, Chrome usually blocks any CORS request originating from this origin.
You can install this extension:
https://chrome.google.com/webstore/detail/allow-cors-access-control/lhobafahddgcelffkeicbaginigeejlf?hl=en
Or you can disable the security when running chrome (add the flag):
--disable-web-security

"Access-Control-Allow-Origin" Request Error When Accessing API [duplicate]

This question already has answers here:
XMLHttpRequest cannot load XXX No 'Access-Control-Allow-Origin' header
(11 answers)
Closed 3 years ago.
I'm unable to retrieve data from the Rescue Time API. I'm making a request in a JavaScript file using the jQuery get() method. Here is a look at the JavaScript related to the API GET request:
$.get('https://www.rescuetime.com/anapi/data?key=########################&format=json&restrict_kind=overview', function(data) {
// callback function code...
});
The "key=########################" is the paramater that includes my API key.
When running the script (either locally or on my personal domain), I receive a cross origin error:
XMLHttpRequest cannot load https://www.rescuetime.com/anapi/data?key=########################&format=json&restrict_kind=overview. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access.
I understand that this is happening because i'm requesting content that is on a different domain than the one that is making the AJAX request. That being said, how do I get around this? I've read the CORS MDN documentation, but could not decode what actionable steps I need to follow in order to resolve this issue.
I need some actionable steps.
Set up a CORS proxy using the code from https://github.com/Rob--W/cors-anywhere/ or similar.
https://cors-anywhere.herokuapp.com/ is a public instance running that code, and the way you could use it is by changing your existing code to this:
$.get('https://cors-anywhere.herokuapp.com/https://www.rescuetime.com/anapi/data?key=########################&format=json&restrict_kind=overview', function(data) {
// callback function code...
});
Be aware though that if you do that, your key would potentially be exposed to the operator of that https://cors-anywhere.herokuapp.com/ instance. So if that’s a concern then don’t try it, and instead set up your own proxy at https://some.url.for.your.proxy and change your code to:
$.get('https://some.url.for.your.proxy/https://www.rescuetime.com/anapi/data?key=########################&format=json&restrict_kind=overview', function(data) {
// callback function code...
});
Either way the result will be that your request gets sent through the specified CORS proxy, which forwards the request to the https://www.rescuetime.com/anapi/data… endpoint and then receives the response. The proxy backend then adds the Access-Control-Allow-Origin header to the response and finally passes that back to your requesting frontend code.
Your browser then allows your frontend code to access the response, because that response with the Access-Control-Allow-Origin response header is what the browser sees. Otherwise, if the response lacks Access-Control-Allow-Origin, browsers won’t let your code access it.
A CORS proxy like that is the only option if you want to make the request from frontend JavaScript code running in a browser, and want to consume the response from that frontend code. Otherwise, without the use of such a proxy, browsers will block your code from accessing the response—because the https://www.rescuetime.com/anapi/data… API endpoint doesn’t itself send the necessary Access-Control-Allow-Origin response header.
Your only other option otherwise is to not make the request from your frontend code but instead make the request from whatever backend server-side code you’re running. In that case there’s no browser in the middle enforcing cross-origin restrictions on the request.

Calling Yelp API from frontend JavaScript code running in a browser

Would really appreciate anyone's help. I am relatively new to developing in React, using Mac OSX and Chrome as my browser. I have a small application that attempts to make an async GET request from Yelp Fusion's API using 'isomorphic-fetch', but receive the following error:
Fetch API cannot load https://api.yelp.com/v3/businesses/search?[remaining URL] 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. The response had HTTP status code 500. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
I have done a lot of searching to see what responses to identical issues already exist, but I am left even more confused in how to tackle my problem with my relatively new knowledge to this kind of development environment. (Answers that seem particularly helpful are: Response to preflight request doesn't pass access control check and API Request with HTTP Authorization Header inside of componentDidMount, but I do not really understand how to actually implement those solutions with my environment. Any attempts I make seem incorrect and do not result in a change.).
As a side note: I have installed the Allow-Control-Allow-Origin: * extension on my Chrome browser, but I receive the same error - just a shortened, less elaborate description of it:
Fetch API cannot load https://api.yelp.com/v3/businesses/search?[remaining URL]. Response for preflight has invalid HTTP status code 500
The following is how I call the fetch in my code:
var options = (
method: 'get',
headers: new Headers({
'Access-Control-Allow-Origin': '*',
'Authorization': [my token]
'Content-Type': 'application/json'
})
}
return fetch(url, options);
Is this an issue due to the syntax of my header with Yelp Fusion's OAUTH2 token requirements, do I need to do something proxy-related, or is the reason because of something else? If proxy-related, currently I am running a fully client-driven application and do not use server-side code at all. Would this still be possible given my environment? Any guidance as to which direction I should go and clarification of my misconceptions would be greatly appreciated.
Again, thank you for your help for a growing developer.
This cause of the problem is that https://api.yelp.com/ doesn’t support CORS.
And there’s nothing you can in your own application code to fix that—no matter what you try, you can’t change the fact that https://api.yelp.com/ doesn’t support CORS.
Apparently the Yelp API does support JSONP though; see for example Yelp API Origin http://localhost:8888 is not allowed by Access-Control-Allow-Origin.
So using https://api.jquery.com/jquery.getjson/ or similar in your frontend code would allow you make requests to the Yelp API cross-origin from your frontend code.
A related issue in the GitHub issue tracker for the Yelp API examples repo confirms no CORS:
TL;DR: No CORS is not supported by api.yelp.com
And another related issue:
As I answered in #99 , we do not provide the CORS headers necessary to use clientside js to directly make requests to the api.
Both of the comments cited above are from a Yelp engineer.
So what the means is, there’s no way your frontend JavaScript code can make requests directly to Yelp API endpoints and get normal responses (as opposed to JSONP responses).
Specifically, because responses from the https://api.yelp.com/v3/businesses/search API endpoint don’t include the Access-Control-Allow-Origin response header, browsers will not allow your frontend JavaScript code to access those responses.
Also, because your request includes the Authorization and a Content-Type header with the value application/json, your browser does a CORS preflight options request before ever attempting the actual GET request you’re trying to send.
And that preflight is what’s specifically failing in this case. But any other request you make from the frontend code to that API endpoint would also fail—even if it didn’t trigger a preflight.

CORS request in react

Getting this error when trying to get stuff from the Twitter API using simple-twitter:
XMLHttpRequest cannot load https://api.twitter.com/1.1/statuses/user_timeline.json. 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. The response had HTTP status code 400
I'm basically doing exactly what it says in the react docs, but with the relevant line replaced:
componentDidMount: function() {
twitter.get('statuses/user_timeline', function(error, data) {
if(this.isMounted()){
this.setState({tweets: data})
console.dir('callback')
}
}.bind(this));
}
The callback function seems to never fire, which I assume is due to the request not completing.
What am I missing here?
The issue here is the module you're using is written for Node, not the browser.
Whilst in the browser, you can't make requests outside of your origin (in this case localhost:3000) unless the requested resource is served with the appropriate Access-Control-Allow-Origin header.
In this case the browser makes a preflight (OPTIONS) request to the same resource to see whether the CORS checks pass and it can safely respond. In this case it can't because Twitter's API doesn't allow your origin.
You can avoid these limitations if the API supports JSONP, but as of V1.1 of the Twitter API, only OAuth is supported.
This means that to access the Twitter API from the client, you'll need to authenticate inside your session, in order to generate an OAuth token that you can use to make requests. Take a look at the codebird-js library.
Alternatively, you can use the simple-twitter module from a server and forward requests from your browser on to the Twitter API.

Categories

Resources