AngularJS: POST Data для внешнего REST API
У меня есть базовая настройка службы AngularJS, например:
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.
Ответы
Ответ 1
Ваши две проблемы на самом деле являются одной проблемой. Запрос OPTIONS является частью процесса CORS. Для запросов POST браузер сначала отправляет вызов OPTIONS, и сервер отвечает, если это нормально для его выполнения.
Если запрос OPTIONS завершился с ошибкой, Angular/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')
x-xrsf-token для angular 'для предотвращения CSRF. Возможно, вам придется добавить больше заголовков, в зависимости от того, что вы отправляете от клиента.
Вот очень хорошее руководство по CORS: https://developer.mozilla.org/en-US/docs/HTTP/Access_control_CORS
Ответ 2
В AngularJS для работы CORS вам также придется перезаписать настройки по умолчанию angular 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 в true недостаточно. Запрос AJAX также отправьте с заголовком X-Requested-With, который указывает, что они являются AJAX. Удаление заголовка необходимо, поэтому сервер не отклоняет входящий запрос.
Примечание. Ответ работает только для более ранней версии AngularJS, предшествующей 1.2. С 1,2 и выше вам не нужно ничего делать, чтобы включить CORS.
Ответ 3
Лучше решить эту проблему на сервере. На apache вы можете решить это как в файле .htaccess
. Это источник боли для разработки angular и может быть решен в angular, но, вероятно, это не лучший способ сделать это.
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"