M
M
mpotemkin2014-12-02 06:50:52
Angular
mpotemkin, 2014-12-02 06:50:52

AngularJS + $httpProvider + CORS - what's wrong?

Hello!
I am making an application in AngularJS. I ran into a CORS issue when trying to use Angular-UI Typeahead and loading cities from the google map api.
There is following app.js code

.config(
  [          '$stateProvider', '$urlRouterProvider', '$controllerProvider', '$compileProvider', '$filterProvider', '$provide', '$httpProvider', 
    function ($stateProvider,   $urlRouterProvider,   $controllerProvider,   $compileProvider,   $filterProvider,   $provide, $httpProvider) {
        
        // lazy controller, directive and service
        app.controller = $controllerProvider.register;
        app.directive  = $compileProvider.directive;
        app.filter     = $filterProvider.register;
        app.factory    = $provide.factory;
        app.service    = $provide.service;
        app.constant   = $provide.constant;
        app.value      = $provide.value;

        $httpProvider.interceptors.push('TokenInterceptor');

        //

service.js
.factory('TokenInterceptor', function ($q, $window, $location, AuthenticationService) {
    return {
        request: function (config) {
            config.headers = config.headers || {};
            if ($window.sessionStorage.token) {
                config.headers.Authorization = 'Bearer ' + $window.sessionStorage.token;
            }
            return config;
        },

        requestError: function(rejection) {
            return $q.reject(rejection);
        },

        /* Set Authentication.isAuthenticated to true if 200 received */
        response: function (response) {
            if (response != null && response.status == 200 && $window.sessionStorage.token && !AuthenticationService.isAuthenticated) {
                AuthenticationService.isAuthenticated = true;
            }
            return response || $q.when(response);
        },

        /* Revoke client authentication if 401 is received */
        responseError: function(rejection) {
            if (rejection != null && rejection.status === 401 && ($window.sessionStorage.token || AuthenticationService.isAuthenticated)) {
                delete $window.sessionStorage.token;
                AuthenticationService.isAuthenticated = false;
                $location.path("/access/login");
            }

            return $q.reject(rejection);
        }
    };
})

Everything works authorization, the token - everything is fine, we go through all the tabs of the application - everything is fine. But such a thing in the form as Typeahead does not work, it displays an error in the console:
Request from foreign origin blocked: Single origin policy prevents reading remote resource at http://maps.googleapis.com/maps/api/geocode/json?a... This can be fixed by moving the resource to the same domain or enabling CORS .

template.html
<div class="form-group">
                    <label>Местоположение</label>
                    <div class="pos-rlt" ng-controller="TypeaheadLocationCtrl">
                      <i ng-show="loadingLocations" class="fa fa-spinner fa-spin form-control-spin"></i>
                      <input type="text" ng-model="userinfo.location" placeholder="Введите первые буквы названия местоположения" typeahead="address for address in getLocation($viewValue)" typeahead-loading="loadingLocations" class="form-control">
                    </div> 
                  </div>

controller.js
// TypeaheadLocation

  .controller('TypeaheadLocationCtrl', ['$scope', '$http', function($scope, $http) {
    $scope.selected = undefined;

    // Any function returning a promise object can be used to load values asynchronously
    $scope.getLocation = function(val) {
      return $http.get('http://maps.googleapis.com/maps/api/geocode/json', {
        params: {
          address: val,
          sensor: false
        }
      }).then(function(res){
        var addresses = [];
        angular.forEach(res.data.results, function(item){
          addresses.push(item.formatted_address);
        });
        return addresses;
      });
    };
  }])

But as soon as $httpProvider is removed from app.js, Typeahead starts to substitute cities when typing - everything is fine, but user identification authorization does not work. That's it, you can't go anywhere - an authorization error.
I can’t understand what’s the matter, what needs to be changed or what to use in order for everything to work and authorization and selection of the city. Googled and Yandexl - did not find.
It is clear that $httpProvider, but how to fix it? Tried this:
$httpProvider.defaults.useXDomain = true;
delete $httpProvider.defaults.headers.common['X-Requested-With'];

does not work.
Please help. Thank you.

Answer the question

In order to leave comments, you need to log in

2 answer(s)
B
Boris Benkovsky, 2014-12-02
@benbor

See, Google allows requests from any site by returning a header in the Access-Control-Allow-Origin: * response. And your authorization works only thanks to TokenIntercepter, it is he who substitutes the authorization token for all your requests. I checked, Google is working fine, if you put an extra Authorization header on it, then it's definitely not the request Intersepter

request: function (config) {
            config.headers = config.headers || {};
            if ($window.sessionStorage.token) {
                config.headers.Authorization = 'Bearer ' + $window.sessionStorage.token;
            }
            return config;
        },

Intersepter in translation means "interceptor" it intercepts not only sending a request (request), but also a response (response) and errors.
Put a breakpoint in every function in the Interceptor and see how it responds to a Google request.
It's most likely the Response function.

M
mpotemkin, 2014-12-02
@mpotemkin

Yes, the question is still open. I tried to check by URL so that the inceptor would not work - it did not work out. Maybe someone else has thoughts, it is very necessary.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question