Angularjs issue - $http.get not working and changed into OPTIONS - Cross domain

1,531 views
Skip to first unread message

amadese

unread,
Oct 27, 2014, 7:25:39 AM10/27/14
to ang...@googlegroups.com

I am a novice to Angularjs and tried to create a remote service (located on "http://dev.testmyserver2") for using in various applications (located on "http://dev.testmyserver").

This service retrieves various data about a user by using Colfusion and an Oracle database. It works perfectly when I launch the application directly in the browser. Nevertheless when I tried to call the function of this service (defined in the factory) from another application (thanks to a dependency called in the main module of this application), the http GET is modified in OPTIONS (visible in firebug) and I cannot retrieve the data (the status code of the http request is O). The function is correctly called (an alert "Function correctly called" or console.log from this function is correctly called), but no data of the person is retrieved.

I think that it's a problem of Cross domain. But I do not know how to solve it.

Here a little code:

  • THE REMOTE SERVICE with functions for retrieving data from a database
    • MODULE - appRemoteService.js:
var app=angular.module('RemoteService', ['ngRoute', 'ui.bootstrap']);

app
.config(function($routeProvider, $httpProvider, ngDialogProvider){

// disable IE ajax request caching
$httpProvider
.defaults.cache = false;
if (!$httpProvider.defaults.headers.get) {
    $httpProvider
.defaults.headers.get = {};
}
$httpProvider
.defaults.headers.get['If-Modified-Since'] = '0';

// Create the routes
$routeProvider
.when('/home',
{
  templateUrl
: 'template/allPersons.html',
  controller
: 'ctrlPersons'

})

.when('/documentation',
{
  templateUrl
: 'template/documentation.html',
  controller
: 'ctrlDocumentation'
})      

.otherwise({redirectTo:'/home'});  
});    

app
.controller('ctrlPersons', function ($scope, FactoryRemoteService){
   
FactoryRemoteService.getUserFromLogin("test").success(function(personInfo){
        alert
(personInfo["VALUES"][0]["FIRSTNAME"]);
   
});    
});

    • FACTORY - appFactoryRemoteService.js:

app.factory('FactoryRemoteService', function($http){
var factory={};
factory
.getUserFromLogin=function(uid){
   
Alert("Function correctly called");
   
return $http.get('http://dev.testmyserver2/myapp.cfc?method=getUserFromLogin&login=' + uid);
};

return factory;
})

  • MY APPLICATION:
    • MAIN FILE - index.html:
 <title>My app</title>

   
<link rel="stylesheet" href="lib/css/bootstrap-3.1.1/css/bootstrap.min.css">
   
<link rel="stylesheet" href="lib/css/bootstrap-3.1.1/css/bootstrap-theme.min.css">

   
<link rel="stylesheet" href="css/styles.css" rel="stylesheet">
   
<link rel="stylesheet" href="css/select.css" rel="stylesheet">  

</head>

<body>

   
<div class="container">
       
<div class="spacer navbar">

           
<h1 class="nav nav-pills navbar-left">MY APP</h1>

           
<ul class="nav nav-pills navbar-right" data-ng-controller="NavbarController">
               
<li data-ng-class="{'active':getClass('/all-contacts')}"><a href="#/all-contacts">All contacts</a></li>
               
<li data-ng-class="{'active':getClass('/add-contacts')}"><a href="#/add-contacts">Add contacts</a></li>
           
</ul>

       
</div>

       
<ng-view></ng-view>

 
</div>

 
<script src="lib/js/angular.min.js"></script>
 
<script src="lib/js/angular-route.min.js"></script>    
 
<script src="lib/js/angular-sanitize.min.js"></script>      

 
<script src="lib/js/bootstrap.min.js"></script>
 
<script src="lib/js/jquery.min.js"></script>

 
<script src="lib/js/ui-bootstrap-tpls-0.11.0.min.js"></script>    

 
<script src="app/app.js"></script>
 
<script src="app/appService.js"></script>

 
<script src="http://dev.testmyserver2/app/appRemoteService.js"></script>
 
<script src="http://dev.testmyserver2/app/appFactoryRemoteService.js"></script>    

</body>

    • MODULE - app.js:
var app=angular.module('ContactsApp', ['ngRoute', 'ui.bootstrap', 'RemoteService']);

// register the interceptor as a service
app
.factory('HttpInterceptor', ['$q', '$rootScope', function($q, $rootScope) {
   
return {
       
// On request success
        request
: function(config) {
       
// Return the config or wrap it in a promise if blank.
       
return config || $q.when(config);
   
},

   
// On request failure
    requestError
: function(rejection) {
       
//console.log(rejection); // Contains the data about the error on the request.  
       
// Return the promise rejection.
       
return $q.reject(rejection);
   
},

   
// On response success
    response
: function(response) {
       
//console.log(response); // Contains the data from the response.
       
// Return the response or promise.
       
return response || $q.when(response);
   
},

   
// On response failure
    responseError
: function(rejection) {
       
//console.log(rejection); // Contains the data about the error.
       
//Check whether the intercept param is set in the config array.
       
//If the intercept param is missing or set to true, we display a modal containing the error
       
if (typeof rejection.config.intercept === 'undefined' || rejection.config.intercept)
       
{
           
//emitting an event to draw a modal using angular bootstrap
            $rootScope
.$emit('errorModal', rejection.data);
       
}
       
// Return the promise rejection.
       
return $q.reject(rejection);
   
}
};
}]);

app
.config(function($routeProvider, $httpProvider){
// disable IE ajax request caching
$httpProvider
.defaults.cache = false;
if (!$httpProvider.defaults.headers.get) {
    $httpProvider
.defaults.headers.get = {};
}  
$httpProvider
.defaults.headers.get['If-Modified-Since'] = '0';

// Add the interceptor to the $httpProvider to intercept http calls
$httpProvider
.interceptors.push('HttpInterceptor');

$routeProvider
.when('/all-contacts',
{
  templateUrl
: 'template/allContacts.html',
  controller
: 'ctrlContacts'

})
.when('/view-contacts/:contactId',
{
  templateUrl
: 'template/viewContact.html',
  controller
: 'ctrlViewContacts'
})
.otherwise({redirectTo:'/all-contacts'});  

});    


app
.controller('NavbarController', function($scope, $location){
$scope
.getClass=function(path){    
   
if($location.path().substr(0,path.length) == path){
       
return true;
   
}else{
       
return false;
   
}      
}
});

app
.controller('ctrlViewContacts', function ($scope, $routeParams, RemoteServiceFactory){
$scope
.contact = null;

// CALL OF THE REMOTE SERVICE
RemoteServiceFactory.getUserFromLogin("test")
.success(function(personInfo){
    alert
(personInfo["VALUES"][0]["FIRSTNAME"]);
})
.error(function(personInfo, status){
    alert
(status);
});
});

After several search on various forums I tested some solutions, but the problem is always present.

For instance I tried to add:

  //Enable cross domain calls
  $httpProvider
.defaults.useXDomain = true;

 
//Remove the header used to identify ajax call  that would prevent CORS from working
 
delete $httpProvider.defaults.headers.common['X-Requested-With'];

OR

  //Reset headers to avoid OPTIONS request (aka preflight)
  $httpProvider
.defaults.headers.common = {};
  $httpProvider
.defaults.headers.post = {};
  $httpProvider
.defaults.headers.put = {};
  $httpProvider
.defaults.headers.patch = {};

Could you please help me to find a solution to solve this problem?

Many thanks in advance for your reply





Sander Elias

unread,
Oct 27, 2014, 7:42:55 AM10/27/14
to ang...@googlegroups.com
Hi Amadese,

CORS is mainly a server side problem. Have a look at the site I just linked. Probably the answer for your server is right there.

Regards
Sander

amadese

unread,
Oct 27, 2014, 9:01:01 AM10/27/14
to ang...@googlegroups.com
Thanks for the link. I have tried it, but the problem is always present. I have tried server side Coldfusion and/or client side. :-(

Sander Elias

unread,
Oct 27, 2014, 9:14:38 AM10/27/14
to ang...@googlegroups.com
Hi Amadese,

If you open the developer tools in your browser, what is the error you are getting?

Regards
Sander


amadese

unread,
Oct 28, 2014, 3:42:06 AM10/28/14
to ang...@googlegroups.com
Hi,

If I use Firebug, no erro appear, the request OPTIONS appears, with the data, but in my alert the status value is 0, in the header I can seee:

Response header
AllowGET, HEAD, POST, TRACE, OPTIONS
Connectionclose
Content-Typetext/plain; charset=UTF-8
DateTue, 28 Oct 2014 07:36:17 GMT
ServerApache/2.2.3 (Red Hat)
Transfer-Encodingchunked

 Request header
Accepttext/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encodinggzip, deflate
Accept-Languageen-US,en;q=0.5
Access-Control-Request-He...if-modified-since
Access-Control-Request-Me...GET
Connectionkeep-alive
Hosthttp://dev.testmyserver
Originhttp://dev.testmyserver2
User-AgentMozilla/5.0 (Windows NT 6.1; WOW64; rv:32.0) Gecko/20100101 Firefox/32.0

In the response tab I can see:

Reload the page to get source for: http://dev.testmyserver2/cfc/service/myapp.cfc?method=getUserFromLogin&login=test

Sander Elias

unread,
Oct 28, 2014, 6:40:36 AM10/28/14
to ang...@googlegroups.com
Hi Amadese,

You seem to miss the needed headers for CORS, the server needs to provide those. (your app seems to to ok, as you get an response to an option request.)
With the needed headers missing, the browser will come to a full halt on your request, and drop things off while no data comes to your app.

Regards
Sander

Matteo Moci

unread,
Oct 28, 2014, 6:52:33 AM10/28/14
to ang...@googlegroups.com
see http://enable-cors.org/server_apache.html
It would be easier to debug it doing requests from command line, like curl. 

In this way you see the headers replied by the server, 
that should include Access-Control-Allow-Origin "*"


--
You received this message because you are subscribed to the Google Groups "AngularJS" group.
To unsubscribe from this group and stop receiving emails from it, send an email to angular+u...@googlegroups.com.
To post to this group, send email to ang...@googlegroups.com.
Visit this group at http://groups.google.com/group/angular.
For more options, visit https://groups.google.com/d/optout.



--
Matteo Moci
http://mox.fm

Message has been deleted

amadese

unread,
Oct 29, 2014, 7:11:34 AM10/29/14
to ang...@googlegroups.com
I have tested in Chrome and I obtain the message:

XMLHttpRequest cannot load http://dev.testmyserver2/myapp.cfc?method=getUserFromLogin&login=test'. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://dev.testmyserver' is therefore not allowed access. index.cfm:1

Nevertheless I have tested to add this lines in the file myapp.cfc:

    <cfheader name="Access-Control-Allow-Origin" value="*">
    <cfheader name="Access-Control-Allow-Methods" value="POST, GET, PUT, DELETE, OPTIONS">
    <cfheader name="Access-Control-Allow-Headers" value="X-Requested-With, content-type">

But it doesn't work... I do not know if the location of theses lines is correct (I have put on the top of the file)

I think that it's due to that the CORS not supported by IE9

I have equally tried to change the method $http.get into $http.jsonp. The function is correctly called and not changed into OPTIONS), the results are displayed in the response of the console but the status code is 404... and the results are not retrieved by Angularjs.

I do not find solutions to retrieve these data :-( and to solve the problem :-(

Sander Elias

unread,
Oct 29, 2014, 7:23:47 AM10/29/14
to ang...@googlegroups.com

Amadese,

you can’t use Access-Control-Allow-Origin:'*' in a lot of circumstances. In stead of a star, you must put the name of the domain you are calling in there.
in your case, that would probably be: 'dev.testmyserver'

Hope this helps a bit,
Regards
Sander

Adrian Lynch

unread,
Oct 29, 2014, 4:55:27 PM10/29/14
to ang...@googlegroups.com
I've recently battled this in CFML too.
In my CF application I added:

<cfheader name="content-type" value="application/json">
<cfheader name="Access-Control-Allow-Origin" value="http://domain-making-request-goes-here:8889"><!--- *** --->
<cfheader name="Access-Control-Allow-Credentials" value="true"><!--- *** --->
<cfoutput>#serializeJSON(session)#</cfoutput>

The in the client application:

<script>
$(function() {
$("button").click(function() {
$.ajax({
xhrFields: {
withCredentials: true // ***
}
}).done(function(res) {
console.log(res.count);
});
});
});
</script>

<button>Keep Alive</button>

This was all part of a quick test to see if we could keep a session alive as we moved between two applications we're building.

I've marked the important parts with *** in the code above.

As someone has already mentioned, read up on CORS here: http://enable-cors.org/ and remember that it's a server issue, not a client one.

Adrian

--

amadese

unread,
Oct 30, 2014, 11:15:22 AM10/30/14
to ang...@googlegroups.com

For persons who encounter the same problem, I found a solution by using the XDomain third-party library. You have to implement a proxy.html file on the remote server where the service is located, and call the file in a script tag in the main application.

Reply all
Reply to author
Forward
0 new messages