Can't connect to API using React.js fetch method - reactjs

I'm trying to connect to buffer's API (https://buffer.com/developers/api/oauth) via react.js using fetch(), but I'm getting a 400 error response.
This is running on my localhost but the site's accessible from the Internet.
Here's my code:
const queryString = require('query-string');
const parsed = queryString.parse(window.location.search);
const buffer_data = {
client_id: BUFFER_CLIENT_ID,
client_secret: BUFFER_CLIENT_SECRET,
redirect_uri: BUFFER_CALLBACK_URL,
code: parsed.code,
grant_type: 'authorization_code',
};
fetch(BUFFER_ACCESS_TOKEN_URL, {
method: 'post',
body: JSON.stringify(buffer_data),
}).then( data => {
console.log('data response ' + data);
return data.json();
}).then( response => {
console.log(response);
});
And here's the response:
{"error":"invalid_request","error_description":"Invalid grant_type
parameter or parameter missing"}
And the console prints this:
Failed to load https://api.bufferapp.com/1/oauth2/token.json: No
'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'http://myserver.com' is therefore not allowed
access. The response had HTTP status code 400. If an opaque response
serves your needs, set the request's mode to 'no-cors' to fetch the
resource with CORS disabled.
I've tried lots of things, like not serializing the data, trying sending many different headers, using a CORS chrome plugin, etc
Before coding this in react, I've successfully connected using PHP, but to do that I had to add an SSL certificate on my server.
I'm also open to use any library but haven't found one to do this job. Or any other fetching method, like axios?
Many thanks!

I don't know which browser you are using, but you might want to add Allow-Control-Allow-Origin
for your chrome browser (if you are using chrome). This is some issue that seems to occur when you are using localhost with chrome.
Also, i highly recommend using axios for fetching API's, it comes with some easy error logs that can help you pinning down the issue pretty fast.
Greetings!

Related

How to properly setup the barryvdh/laravel-cors in reactjs

I am currently new in ReactJS and facing problem regarding getting the response of API the console log shows of error of this
Access to XMLHttpRequest at 'https://facebook.github.io/react-native/movies.json' from origin 'http://localhost:8000' 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.
they recommend to me that I use the barryvdh/laravel-cors to allow the cors in my API. I will show you guys my front-end code.
componentDidMount() {
axios.get('https://facebook.github.io/react-native/movies.json',{
}).then(function(response){
console.log(response)
})
}
In my logs, I will share here the captured image.
The error is in your Axios request itself, if you clearly see
axios.get('https://facebook.github.io/react-native/movies.json',{})
You've an additional parameter, While you are not passing any headers or other parameters, if you remove the {} then it should work.
axios.get('https://facebook.github.io/react-native/movies.json')
And if you see the results of your console you can see on where it clearly states that OPTIONS request is throwing a 405 status code,
from MDN
The HyperText Transfer Protocol (HTTP) 405 Method Not Allowed response
status code indicates that the request method is known by the server
but is not supported by the target resource.
You'll need to directly access the resource, probably your axios is generating Pre Flight Request with OPTIONS header due to {}, which is being rejected by the resource itself.
You can also try doing it with a simple fetch request,
fetch('https://facebook.github.io/react-native/movies.json')
.then(function(response) {
console.log(response.json())
})
CORS is controlled by backend API and in your case, you don't have control over it which is
https://facebook.github.io/react-native/movies.json.
Browser prevents your code from accessing the response because of the browser can't see Access-Control-Allow-Origin in response.
Things can still get working by making the request through a Proxy can where a proxy sends appropriate CORS header on behalf of your request.
const proxy = "https://cors-anywhere.herokuapp.com/";
const url = "https://facebook.github.io/react-native/movies.json";
fetch(proxy + url)
.then(response => response.text())
.then(contents => console.log(contents))
.catch(() => console.log("CORS Error" + url ))
Making a request through a proxy will work this way
CORS proxy will forward your request to https://facebook.github.io/react-native/movies.json
Return response from https://facebook.github.io/react-native/movies.json with Access-Control-Allow-Origin headers.
Now your browser can see Access-Control-Allow-Origin headers present in the response header.
For more detail explanation you can check out this
https://stackoverflow.com/a/43881141/2850383

Get method is converted to OPTIONS when hitting fetch api in React js

I am trying to hit below api and requires basic auth username and password and method allowed in this is only get
dispatch(requestBegin());
let apiPath = `xxxx/TEST/appservice/api/app/10/10000127201901`;
return fetch(apiPath, {
method: 'get',
headers : {
"contentType":"application/x-www-form-urlencoded",
"Authorization" : 'Basic '+btoa('xxx:xxx'),
},
})
.then((response) => {
dispatch(getEventsEnds(json));
})
.catch((error) => {
dispatch(getEventsEnds());
});
The error loged in console :
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:2200' is therefore not allowed
access. The response had HTTP status code 405. If an opaque response
serves your needs, set the request's mode to 'no-cors' to fetch the
resource with CORS disabled.
OPTIONS http://xxx/appservice/api/app/10/10000127201901 405 (Method
Not Allowed)
Can anyone please eplain when i m trying to hit get api then why is it showing options
That means your API server does not accept CORS request or requests originating from localhost.
Check out your API documentation but my guess is you won't be able to interact directly with it from your web app.
Your best bet is to use a proxy, you can develop one yourself or use something like node-http-proxy to proxy your API calls. (There are php or python equivalents)
The proxy server will be able to issue the requests and will then forward them to your app.
Suggested further reading: type understanding CORS on google and read more about it.
For local development, check out:
https://github.com/Rob--W/cors-anywhere
This issue occurs when the client api URL and server URL don't match, including the port number. In this case you need to enable your service for CORS which is cross origin resource sharing.
use npm install cors
refer this[refer][1]

Http method set in the API call changes when seen in the chrome Dev tools

I am trying to call an API using
createAuthorizationHeader(headers: Headers) {
headers.append('Authorization',
'Bearer ' + JSON.stringify(JSON.parse(localStorage.getItem('access_token')).access_token));}
getAllData() {
let headers = new Headers();
this.createAuthorizationHeader(headers);
return this.http.get('url'
{ headers: headers }
).map((response) => {
response.json();
});
here i am sending the request using the GET Http Method, but in the chrome dev tools i see the Request method is set to Options, which is not allowed in the API.
but if i comment out the headers in the this.http.get then, in the chrome dev tools i see the correct http request method.
Any suggestions why this might be happening?
You're most likely making a cross-domain request here.
When making a cross-domain (CORS) request, Chrome will send a pre-flight (OPTIONS) requests to your API first to discover if the AngularJS request should be trusted by your API.
Therefore if you're going to host your AngularJS client and API on different domains, you'll have to allow OPTIONS requests and ensure CORS is properly configured on your API.

API Request with HTTP Authorization Header inside of componentDidMount

I'm very new to React, and to practice, I am trying to build an application that fetches information from the Yelp API, but I'm having trouble getting a response. Yelp Fusion v3 requires an 'access_token'(which I've successfully received as a response in Postman). So to make this request in my application, I am using Axios. When I am making this request inside of componentDidMount(), as a response I get
XMLHttpRequest cannot load https://api.yelp.com/v3/businesses/search?term=sushi&location=Boston. 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:8080' is therefore not allowed access. The response had HTTP status code 500.
Though it may seem that I am incorrectly specifying the access_token and parameters, when running the same code in a separate file(not part of the application), I get the JSON response that I am looking for in my app.
Here is my componentDidMount():
componentDidMount: function () {
axios.get('https://api.yelp.com/v3/businesses/search?term=Sushi&location=Boston',{
headers: {
Authorization: `Bearer ${token}`
}
})
.then(function(res){
console.log(res)
})
.catch(function(err){
console.log(err)
})
},
I've tried the Yelp node module as well, but I am having no luck. Please help!
This error is a Cross-Origin error.
Web browsers have a catch with AJAX requests: They need to be addressed to the same origin or be authorized by the third-party itself, otherwise they are blocked. Since you have no control over Yelp, I suggest you take a workaround.
Available workarounds
You use something like jsonp. This method basically consists in making the request in a <script> tag. The server will wrap the response inside a Javascript script and it will be loaded unto the page. (https://en.wikipedia.org/wiki/JSONP). The server MUST offer this format for that workaround to work.
You use a reverse proxy. You can set NodeJS to act as one. In this setup, you will make your yelp request to your origin who will redirect it to the yelp server. This works because your Node proxy does not have the same limitations as your browser. (ex: https://github.com/nodejitsu/node-http-proxy)
There may be other ways to get around this, but those are popular methods.
Hope this helps.

Bad Request (400) When Trying to Authenticate Harvest API in React

So I'm building a status board for our internal use as developers here in the office. It will show number of commits, hours tracked, etc.
I am following this model for authenticating. After a user logs in with harvest it redirects them back to the app with the code param as a query string, I'm then taking that query string and passing it to a state to then do a fetch to get the access token (so that I can later pull API data).
What happens, is the login is successful but when you are redirected back to the app the fetch throws a Bad Request (400) error. I have tested in Postman and can get the correct response so I'm not sure what the issue is...
Here is some of the JS from the Main component that sets the states if there is a code param:
harvestState() {
// grab URL params
let urlParams = queryString.parse(location.search);
console.log(urlParams);
console.log(urlParams.code);
// set the state based on the paramater passed back
urlParams.code ? (
this.setState({
harvestcode: urlParams.code
})
) : (
this.setState({
harvestcode: 'none'
})
);
}
componentWillMount(){
this.harvestState();
}
And here is the fetch function in my Harvest component:
getHarvest(){
const clientSecret = 'XXXXXXXXXX';
// Set Harvest Headers
const harvestHeaders = {
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
method: 'POST',
mode: 'no-cors',
body: {
'code': this.props.code,
'client_id': this.props.clientid,
'client_secret': clientSecret,
'redirect_uri': 'http://dash.mycompany.me',
'grant_type': 'authorization_code'
}
};
fetch('https://mycompany.harvestapp.com/oauth2/token', harvestHeaders)
.then( response => response.json() )
.then( token => {
console.log(token);
} )
}
componentDidMount(){
if( this.props.code !== 'none' ){
this.getHarvest();
}
}
Is there something here that I am doing wrong? Why does it always return a bad request? Any help would be appreciated. Thank you!
At least one issue you have is that when you use mode: 'no-cors' you’re telling the browser to handle the response as an opaque response, which means that you’re telling the browser to not make any properties of the response object accessible from JavaScript.
So if you make a mode: 'no-cors' request, response => response.json() is going to fail.
The only purpose for no-cors in practice is in combination with Service Workers when you’re just caching resources (e.g., images) from responses, without need to get properties of the responses.
Anyway, given that the client Web app making the requests in your deployment is running from a different origin than the server the requests are sent to, browsers are going to block the requests unless the server responds with the necessary CORS headers—Access-Control-Allow-Origin, for a start. For an explanation, see the MDN article HTTP access control (CORS).
That is, browsers block cross-origin requests made from JavaScript unless the server the requests are sent to opts-in to allowing those, with the Access-Control-Allow-Origin, etc., response headers. The reason Postman doesn’t block such requests is that Postman is not an arbitrary Web app running at some specific origin on the Web but is instead a browser plugin that you’ve intentionally installed. So it’s not bound the cross-origin restrictions browser enforce for Web apps.

Resources