405 Error with POST request (AngularJS $http) - angularjs

I want to do a post request on Google Contacts API with AngularJS $http.
I tried to do this :
var config = {
headers: {
// "Content-Type": "application/json",
"Authorization": "Bearer " + gapi.auth.getToken().access_token,
"GData-Version": "3.0"
}
}
var data = {
"test": "test"
}
$http.post('https://www.google.com/m8/feeds/contacts/default/full/', data, config);
But it returns "XMLHttpRequest cannot load https://www.google.com/m8/feeds/contacts/default/full/. Response for preflight has invalid HTTP status code 405"
This request is working (returns 201 created) on a RestClient like Postman.
If someone could explain to me why this method is not allowed from a browser.

I believe the issue is that the https://www.google.com/m8/feeds/contacts API simply doesn't support OPTIONS requests. The 405 response is essentially saying the endpoint doesn't support the OPTIONS request, not necessarily that it doesn't support POST.
The solution is to use Google's own JavaScript API library rather than Angular's $http service.
You can use the JavaScript client library to interact with Google APIs, such as People, Calendar, and Drive, from your web applications.
There's also some documentation on how Google's API library supports CORS requests.
There may be some Angular wrapped versions of this library to make your life a little easier however I haven't dug around.

Related

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.

CORS issue with calling Quandl API with angular $http

I am trying to get data from Quandl (https://www.quandl.com/data/YAHOO/MSFT.json) web site. It works perfectly well with all browsers and other REST clients like Postman.
My angular $http call looks quite simple and I've tried quite a few combinations with or without header.
$http({
url: 'https://www.quandl.com/data/YAHOO/MSFT.json',
method: "GET",
headers: {
"X-Content-Type-Options": "nosniff",
"X-Frame-Options": "SAMEORIGIN",
"X-Rack-CORS": "preflight-hit; no-origin"
}
})
.then(res => {
console.log(res);
});
getting a standard error
XMLHttpRequest cannot load
https://www.quandl.com/data/YAHOO/MSFT.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:2992' is therefore not allowed
access. The response had HTTP status code 405.
However, vendor seems to support CORS
http://help.quandl.com/article/280-does-the-quandl-api-support-cross-origin-resource-sharing-cors
Any ideas?
Thanks
Quandl supports CORS when requesting data through the API. The URL you are trying to use is for the web page of the dataset. To make an API call instead, all that you have to do is find the Quandl code for that dataset and pass it to the API.
You can find the Quandl code at the top right of that page (YAHOO/MSFT in this case). So, the appropriate API call for your request would be https://www.quandl.com/api/v3/datasets/YAHOO/MSFT.json.
You can see full documentation for working with the Quandl API here: https://www.quandl.com/docs/api.
Have you checked if you are using the correct URL? Quandl proposes a different URL for its API. See Quandl - How do I download a dataset using the API
Your URL should be: https://www.quandl.com/api/v3/datasets/YAHOO/MSFT-MSFT-Microsoft-Corporation.json

Salesforce and Angular with separate servers

I have two sets of servers:
apache serving up html/js/css pages in the angular flavor
SalesForce backend rest apis serving up Json
Salesforce has OAuth authentication, but it is not letting the javscript even perform an OPTIONS call in order to figure out if it can do the POST call it really wants to:
Is there any way to get around this without a proxy or jsonp?
is the Salesforce APEX Rest API configured wrong? the source domain is already whitelisted...
Update:
so some angular code to make the call:
var config = {
method: 'POST',
url: SalesforceRestApi,
headers: {
Authorization: "OAuth "+authToken,
"Content-Type": "application/pdf"
},
data : caseRequest,
};
var http = angular.element(document.body).injector().get('$http');
http(config).then(function(response){ console.log(response); });
this code here returns the good old Chrome error:
XMLHttpRequest cannot load https://xxx.salesforce.com/services/apexrest/xxx/v1/. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://sample.com' is therefore not allowed access. The response had HTTP status code 401.

AngularJS: $http.post throws error

I am using Request Bin to post some data. In my controller, I have the following code:
$http.post('http://requestb.in/redacted', fooBar).
success(function(data) {
$scope.fooBarPostedSuccess = true;
}).
error(function(err) {
console.log("Error while posting to Request Bin");
console.log("Error Info : " + err);
});
This is triggered by means on a button on the UI. Now when this gets triggered, the data is not posted to Request Bin and I get this error:
XMLHttpRequest cannot load http://requestb.in/redacted.
Origin http://localhost:3000 is not allowed by Access-Control-Allow-Origin.
How do I post data to request bin through an AngularJS controller? Also, what does the above error mean?
EDIT : I wish to add here that I am using Node.js with AngularJS. Is this something to do with Node perhaps?
Ah yes... you are dealing with cross-domain scripting issues. This is not an AngularJS problem, but a browser security limitation and a VERY common friction point.
You cannot POST/PUT/DELETE to another domain (different from the one which is hosting -- localhost in your case) without doing some Cross-Origin Resource Sharing (CORS). You are limited to GET for a cross-domain HTTP request.
You have two options:
See if your API supports any cross-domain capabilities. This might be via CORS or it might be via an overloaded GET API or JSONP.
Proxy requests through your server. Since you are using Node.js, proxying REST through your server is extremely simple... you just need to set up a route handler (like /api/redacted) in your Node.js server and then make a new request to your actual API server with something like Restler (NPM package) and return the result back to your client.
Hope this helps!
EDIT:
Your API supports JSONP (Your API Docs). You should be able to use Angular's JSONP function to access your API's JSONP capabilities. (Angular.js JSONP docs).
Since you want to be able to POST to the service, you will need to use the second approach.
CORS allows both GET and POST
http://en.wikipedia.org/wiki/Cross-origin_resource_sharing
http://www.w3.org/TR/cors/
https://developer.mozilla.org/en-US/docs/HTTP/Access_control_CORS
Now, that that's out of the way...
I too have found that angular's $http won't let me POST cross domain. I was suspicious about that though because I have jquery ajax calls in other projects that can post cross domain just fine. So, I swapped my $http POST with $.ajax POST and that worked.
// $http({
// url: url,
// method: "POST",
// data: data
// })
// .success(successCallback)
// .error(errorCallback)
// ole reliable
$.ajax({
type : "POST",
url : url,
data : data,
success : successCallback,
error : errorCallback,
cache : false,
dataType : 'json',
})
You can use PutsReq instead of RequestBin. PutsReq supports CORS.

Resources