@mpotemkin

AngularJS + $httpProvider + CORS — что не так?

Здравствуйте!

Делаю приложение на AngularJS. Столкнулся с проблемой CORS при попытке использовать Angular-UI Typeahead и подгрузкой городов из api google map.

Есть следующий код app.js
.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);
        }
    };
})


Все работает авторизация, токен - все хорошо, ходим по всем вкладкам приложения - все замечательно. Но не работает такая штука в форме как Typeahead выводит ошибку в консоли:

Запрос из постороннего источника заблокирован: Политика одного источника запрещает чтение удаленного ресурса на http://maps.googleapis.com/maps/api/geocode/json?a... Это может быть исправлено путем перемещения ресурса в тот же домен или включением 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;
      });
    };
  }])


Но стоит убрать в app.js $httpProvider как Typeahead начинает работать подставлять города при наборе - все хорошо, но не работает авторизация идентификация пользователя. Все, никуда зайти нельзя - ошибка авторизации.

Не могу понять в чем дело, что нужно изменить или что использовать, чтобы все работало и авторизация и подбор города. Гуглил и яндексил - не нашел.

Понятно что $httpProvider, но как это исправить? Это пробовал:
$httpProvider.defaults.useXDomain = true;
delete $httpProvider.defaults.headers.common['X-Requested-With'];

не работает.

Прошу помощи. Спасибо.
  • Вопрос задан
  • 3326 просмотров
Пригласить эксперта
Ответы на вопрос 2
benbor
@benbor
Помог ответ - не забудь лайкнуть
Смотрите, Гугл разрешает делать запросы с любых сайтов, возвращая заголовок в ответе Access-Control-Allow-Origin: *. А ваша авторизация работает только благодаря TokenIntercepter именно он подставляет токен авторизации для всех ваших запросов. Я проверил, гугл работает нормально, если ему подсовывать лишний Authorization заголовок, значит дело точно не в request Intersepter
request: function (config) {
            config.headers = config.headers || {};
            if ($window.sessionStorage.token) {
                config.headers.Authorization = 'Bearer ' + $window.sessionStorage.token;
            }
            return config;
        },

Intersepter в переводе обозначает "перехвадчик" он перехватывает не только посылку запроса(request), но и ответ (response) и ошибки.
Поставьте брекпоинт в каждую функцию в интерсептере, и посмотрите, как он реагирует на запрос в гугл.
Скорее всего дело в Response функции
Ответ написан
Комментировать
@mpotemkin Автор вопроса
Да уж, вопрос так и остался открытым. Пытался сделать проверку по URL, чтобы не срабатывал inceptor - не вышло. Может есть у кого-то еще мысли, очень нужно.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы