2013-06-25 4 views
16

У меня есть базовая настройка AngularJS службы, как так:AngularJS: POST данные на внешний REST API

app.factory('User', function($resource) { 
return $resource('http://api.mysite.com/user/:action:id/:attr', {}, { 
    history: { 
     method: 'GET', 
     params: { 
      attr: 'history' 
     } 
    }, 
    update: { 
     method: 'POST', 
     params: { 
      name: 'test' 
     } 
    } 
}); 
}); 

и я использую его так:

User.history({id: 'testID'}, function(data) { 
    console.log('got history'); 
    console.log(data); 
}); 
User.update({id: 'me'}, function(data) { 
    console.log('updated'); 
    console.log(data); 
}); 

Проблема одна: User.update(), несмотря на то, что метод установлен на POST, продолжает отправлять OPTIONS в качестве метода запроса.

Хотя инструменты Chrome Dev сообщают о заголовке запроса Access-Control-Request-Method: отправляется POST (не уверен, что это что-то значит).

Проблема два: я получаю сообщение об ошибке с CORS, несмотря на эти заголовки, установленные в коде API:

header('Access-Control-Allow-Origin: *'); 
header("Access-Control-Allow-Methods: PUT, GET, POST, DELETE, OPTIONS"); 

Эта проблема показывает только, хотя, если сделать не-GET запрос.

Каков правильный способ справиться с этим? Я также заглянул в JSONP, но при этом это RESTful api, я не уверен, как обойти проблемы только с поддержкой GET.

ответ

14

Ваши две проблемы на самом деле являются одной проблемой. Запрос OPTIONS является частью процесса CORS. Для запросов POST браузер сначала отправляет вызов OPTIONS, и сервер отвечает, если это нормально для его выполнения.

Если запрос OPTIONS не удался, Угловая/Chrome показывает причину в консоли. Например:

OPTIONS https://*** Request header field Content-Type is not allowed by Access-Control-Allow-Headers. angular.min.js:106 

XMLHttpRequest cannot load https://***. Request header field Content-Type is not allowed by Access-Control-Allow-Headers. 

Вы, вероятно, придется установить Access-Control-Allow заголовки на сервере тоже:

header('Access-Control-Allow-Headers: Content-Type, x-xsrf-token') 

х-xrsf-маркер для углового»для предотвращения CSRF. Возможно, вам придется добавить больше заголовков, в зависимости от того, что вы отправляете от клиента.

Вот очень хороший гид по CORS: https://developer.mozilla.org/en-US/docs/HTTP/Access_control_CORS

+0

Браузер, отправляющий запрос OPTIONS, а затем запрос POST, был там, где была моя проблема. Сервер не настроен для ответа на начальные ВАРИАНТЫ. Однако мне не нужно было ничего делать с x-xsrf-токеном. Используемый код здесь для обработки всех необходимых заголовков: http://stackoverflow.com/questions/13293157/backbone-slim-php-access-control-allow-headers-can-get-information-cant/13530329#13530329 –

+1

это была моя проблема. Спасибо. Если вы используете node/express, следуйте инструкциям «включить предполетные» здесь, чтобы получить работу cors: https://github.com/troygoode/node-cors/ – JasonS

7

В AngularJS сделать CORS работы вам также придется переписать настройки по умолчанию углового httpProvider:

var myApp = angular.module('myApp', [ 
    'myAppApiService']); 

myApp.config(['$httpProvider', function($httpProvider) { 
     $httpProvider.defaults.useXDomain = true; 
     delete $httpProvider.defaults.headers.common['X-Requested-With']; 
    } 
]); 

Просто установка useXDomain истина недостаточно. Запрос AJAX также отправляет с заголовком X-Requested-With, который указывает их как AJAX. Удаление заголовка необходимо, поэтому сервер не отклоняет входящий запрос.

Примечание: Ответ работает только для пожилого AngularJS версии, предшествующей 1.2. С 1,2 и выше вам не нужно ничего делать, чтобы включить CORS.

+6

Это действительно не было необходимо, так как у меня есть доступ к api server и добавлен 'header ('Access-Control-Allow-Headers: X-Requested-With');' который я предполагаю, исправляет проблему, о которой вы говорите. –

+0

Хороший отзыв. Я не знал, как настроить заголовок заголовка allow. Спасибо. –

+0

Возможно, вам пришлось сделать это со старыми угловыми версиями, но я знаю, что в угловом 1.2.x вам не нужно это делать. После ответа Нарретца я работаю для меня. – JasonS

0

Лучше решить эту проблему на сервере. На apache вы можете решить это в файле .htaccess. Это источник боли для углового развития и может быть разрешен также угловым, но, вероятно, это не лучший способ сделать это.

Header set Access-Control-Allow-Origin "*" 
Header add Access-Control-Allow-Headers "origin, x-requested-with, content-type" 
Header add Access-Control-Allow-Methods "PUT, GET, POST, DELETE, OPTIONS"