Call external API by Angular JS - angularjs

I'm calling my API on PHP server by Angular JS:
$http({method: 'POST', url: 'my api...',
And my call is always canceled and generated the error:
XMLHttpRequest cannot load http://kni.prz.edu.pl/querye/api/querye. Origin http://localhost is not allowed by Access-Control-Allow-Origin.
How to enable Cross Requests in Angular JS?
The canceled is not from server.

It's likely that the issue is in fact on the server side. You need to add a response header to allow cross domain requests:
Access-Control-Allow-Origin: *
Be aware that adding this will allow any domain to send requests to your host.
If you don't have control of the server, you'll need to try JSONP, see: $http.jsonp

To enable cross site requests
angularjs $http docs
Most probably you won't get this error when running a deployed instance as you won't be on the localhost.
For testing purposes, you can do:
myApp.config(['$httpProvider', function($httpProvider) {
$httpProvider.defaults.useXDomain = true;
delete $httpProvider.defaults.headers.common['X-Requested-With'];
}]);

Related

Issue with CORS after adding Stormpath Angular SDK

I am working on SPA MEAN app, I was developing it against Apiary mock APIs, which has the following CORS headers set:
Access-Control-Allow-Methods → OPTIONS,GET,HEAD,POST,PUT,DELETE,TRACE,CONNECT
Access-Control-Allow-Origin → *
Access-Control-Max-Age → 10
It all works fine and angular can access it using $http angular service just fine. However after adding Stormpath Angular SDK all these requests fail with following error:
XMLHttpRequest cannot load https://xxx.apiary-mock.com/workshops?type=favourite. Credentials flag is 'true', but the 'Access-Control-Allow-Credentials' header is ''. It must be 'true' to allow credentials. Origin 'http://localhost:8000' is therefore not allowed access.
I am trying to get to figure out why these requests are rejected and at what point these headers are added?
Thank you for finding this issue. The Stormpath Angular SDK does have an interceptor which sets the withCredentials: true flag for all requests. Please see the code here.
The intention is to ensure that our authentication cookies are always sent, even in a cross-domain situation. But I can see how this will be problematic if your Angular application is talking to other APIs that don't require cookies to be sent.
As a workaround, you can override our interceptor by simply adding another one:
angular.module('myapp', [
'stormpath',
'stormpath.templates'
]).config(function ($httpProvider) {
$httpProvider.interceptors.push(function() {
return {
request: function(config) {
config.withCredentials=false;
return config;
}
};
});
});
I've created an issue to discuss a better solution: https://github.com/stormpath/stormpath-sdk-angularjs/issues/72
Any time you have a SPA client served from one domain (e.g. localhost:8080) and you want that client to access an API on another domain (xxx.apiary-mock.com), the browser requires that the server domain add CORS headers correctly.
If the client and server domains are different, the browser's security model requires the server to indicate which client domains may access the server by setting the Access-Control-Allow-Origin response header (in addition to other relevant Access-Control-* headers).
I have how to work around it add these headers to apiary:
+ Response 200 (application/json)
+ Headers
Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods: OPTIONS,GET,HEAD,POST,PUT,DELETE,TRACE,CONNECT
Access-Control-Allow-Origin: http://localhost:8000
I am still trying to figure out where does Stormpath make those headers required though.

Angularjs: $http response set-cookie is not work with CORS

I am using angular and java building a small website.
I try to write a auth system, but i meet some problems with cookie.
My web app is run on localhost:8081 while my java servlet is on localhost:8888.
In my java code:
response.addHeader("Access-Control-Allow-Origin", "http://localhost:8081");
response.addHeader("Access-Control-Allow-Headers", "X-Requested-With");
response.addHeader("Access-Control-Allow-Credentials", "true");
In my angular code:
$httpProvider.defaults.withCredentials = true;
$httpProvider.defaults.useXDomain = true;
delete $httpProvider.defaults.headers.common['X-Requested-With'];
actually I've tried reading
Set-Cookie in HTTP header is ignored with AngularJS
Angularjs $http does not seem to understand “Set-Cookie” in the response
$http response Set-Cookie not accessible
but I still meet strange problems.
My first login: you can find that the server reponse a JSESSIONID and a mobile cookie in set-cookies header.
but I check the chrome developer tool and find the resource>cookies empty.
after login, I send another request to the server to get some list:
but the strange thing is chrome send the JSEESIONID which is send from sever to client on the first login but can't find in the chrome developer tool. while chrome don't send the 'mobile' cookie which is created by my self.
I set my cookie in server with:
CookieUtils.setCookie(response, "mobile",String.valueOf(customer.getPhone()), 3600*24*7, "/","localhost");
request.getSession().setAttribute("user", customer);
request.getSession().setMaxInactiveInterval(3600*24);
what can i do if i want to get the cookie in $http response and set it, and when request other thing with this cookie like my 'mobile' cookie, because i want to do authentication this way.
while, the same code working with firefox is just ok, but not work in chrome 43.0.2357.65 m ,wtf..
Adding
$httpProvider.defaults.withCredentials = true;
with your requests, otherwise the cookie would be set.

Getting "No 'Access-Control-Allow-Origin' header is present on the requested resource" with Angularjs

i am try to create a SPA with Angular. I have to consume the a service form different server. It is a java based service. Here i am getting "No 'Access-Control-Allow-Origin' header is present on the requested resource"
angular.module('tableApp', [])
.config(function ($httpProvider) {
//Enable cross domain calls
$httpProvider.defaults.useXDomain = true;
$httpProvider.defaults.withCredentials = true;
delete $httpProvider.defaults.headers.common["X-Requested-With"];
$httpProvider.defaults.headers.common["Accept"] = "application/json";
$httpProvider.defaults.headers.common["Content-Type"] = "application/json";
//Remove the header used to identify ajax call that would prevent CORS from working
delete $httpProvider.defaults.headers.common['X-Requested-With'];
})
.controller('tableCtrl', ['$scope', '$http', '$timeout', function ($scope, $http) {
var bassURL = 'http://[server ip]:8080/ABC/resource/XYZ'
$http.get(bassURL + '/getTypes').success(function (Type) {
$scope.Type = Type;
});
}
])
Please help.
Your browser is using the CORS protocol to verify access to the service, to prevent cross-site scripting attacks. You need to enable CORS support on the server (adding the Access-Control-Allow-Origin header allowing the site where your Angular site is hosted). Alternatively, you need to use one of the pre-CORS hacks for getting JSON cross-site, and your server needs to provide support for it.
Step 1:
Verify that your angular app is actually hitting a valid URL.
Do this through Fiddler or Postman
Step 2:
Verify that your client AngularJS application and server are running at the same URL and port.
If you intend on having them running on different ports / URLs, you'll need to setup CORS on your java application as mentioned in other comments.
Step 3 (if using Step 2):
Specify a append a JSON_CALLBACK parameter to your URL.
SO Example
Example

Angularjs - $resource causing a 404 - method: OPTIONS

I am trying to get a basic $resource request via angularjs. I am running this on my local computer.
However, I get a 404. A simple get request on the browser loads the json.
Here is the request shown by chrome devtools. (Question: why is the request mode: OPTIONS? Could that be the problem?)
Request URL:http://example.com/api/rentable_properties.json
Request Method:OPTIONS
Status Code:404 Not Found
Here is my controller that is attempting to make the request:
'use strict';
angular.module('adminApp')
.factory('Property', function($resource)
{
return $resource('http://example.com/api/rentable_properties.json/:propertyId');
});
angular.module('adminApp')
.controller('PropertiesCtrl', function ($scope, Property, $location) {
$scope.properties = Property.query()
The answer here is that your browser is running into a cross domain issue
See http://metajack.im/2010/01/19/crossdomain-ajax-for-xmpp-http-binding-made-easy/ for an explanation and Why am I getting an OPTIONS request instead of a GET request? for a question basically the same as yours.
As mentioned by #JSager, the problem was a cross domain issue.
Since I had control over the server side (running a Rails server), I had to change the server to it to receive cross-site requests.
In my case, I had to install a gem and follow it's instructions.
https://github.com/cyu/rack-cors
This fixed the issue for me. No changes made on the Angularjs based app.

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