Angular ресурс, как сохранить заголовок ajax и включить cors в одно и то же время

В моих файлах ng-resource я включаю заголовок ajax:

var app = angular.module('custom_resource', ['ngResource'])

app.config(['$httpProvider', function($httpProvider) {
    //enable XMLHttpRequest, to indicate it ajax request
    //Note: this disables CORS
    $httpProvider.defaults.headers.common["X-Requested-With"] = 'XMLHttpRequest';
}])

app.factory('Article', ['$resource', function($resource) {
    return $resource('/article/api/:articleId', {articleId: '@_id'}, {
        update: {method: 'PUT'},
        query: {method: 'GET', isArray: true}
    })
}])

Итак, я могу отделить запрос ajax и non-ajax и ответ соответственно (отправить данные json, например res.json(data), или отправить всю html-страницу, например res.render('a.html')

например, в моем обработчике ошибок, мне нужно решить отобразить страницу error.html или просто отправить сообщение об ошибке:

exports.finalHandler = function(err, req, res, next) {
    res.status(err.status || 500)
    var errorMessage = helper.isProduction() ? '' : (err.message || 'unknown error')

    if (req.xhr) {
        res.json({message: errorMessage})
    }
    else {
        res.render(dir.error + '/error_page.ejs')
    }
}

Но теперь мне нужно сделать запрос CORS на другие сайты. Можно ли делать запрос CORS, сохраняя заголовок ajax? или другими способами я могу идентифицировать запрос ajax и non-ajax с сервера?

В случае, если мой вопрос не ясен, есть соответствующая статья о angular и CORS http://better-inter.net/enabling-cors-in-angular-js/

В принципе, нам нужно удалить заголовок xhr, чтобы включить cors для другого сервера, но мне нужен заголовок для моего собственного сервера

ИЗМЕНИТЬ 2:

сегодня я попытался интегрировать карту google, и я получил эту ошибку:

XMLHttpRequest cannot load http://maps.googleapis.com/maps/api/geocode/json?address=Singapore&sensor=false. Request header field X-Requested-With is not allowed by Access-Control-Allow-Headers.

Ответы

Ответ 1

Если вы используете последнюю версию angular.js, вы можете сделать это

Сначала добавьте заголовок xhr (что вы сделали правильно)

    $httpProvider.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';

Затем в вашей функции поиска по карте google

var searchAddress = function(address) {
    var params = {address: address, sensor: false};
    //Note: google map rejects XHR header
    $http.get(google_map_web_api_url, {params: params, headers: {'X-Requested-With': undefined}})
        .success(function(data, status, headers, config) {
        })
        .error(function(data, status, headers, config) {
        })
}

Аргумент конфигурации headers, который будет передан, удалит xhr для каждой базы запросов, что означает, что ваши запросы ng-ресурсов не затронуты

Ответ 2

Настройка настраиваемых заголовков в запросах XHR вызывает запрос предварительной проверки.

Таким образом, он не отключает CORS, но ваш сервер, скорее всего, не будет обрабатывать запрос предполетной защиты.

Вдохновленный из этого сообщения: https://remysharp.com/2011/04/21/getting-cors-working

Решение должно заключаться в использовании модуля cors и добавлении следующего к вашему node.js коду перед вашими маршрутами:

var corsOptions = {
    origin: true,
    methods: ['GET', 'PUT', 'POST'],
    allowedHeaders: ['X-Requested-With','Content-Type', 'Authorization']
};

app.options('*', cors(corsOptions)); //You may also be just fine with the default options

Вы можете узнать больше: https://github.com/expressjs/cors

Ответ 4

Есть три решения, которые приходят мне на ум: 1. Попросите администратора сайта включить заголовок x-request-with в CORS. 2. Используйте прокси-сервер. 3. Отправить запрос без заголовка x-request-with.

Эта статья должна дать понять, как работает CORS и как делать запросы CORS. В частности, в этом случае важны раздел "Простые запросы" и раздел "Контроль доступа", особенно описание доступа к управлению-разрешению заголовков.

Как говорится: для простых запросов достаточно-access-control-allow-origin. Однако, если запрос включает настраиваемый заголовок (заголовок, который не включен по умолчанию, например, заголовок с запросом x), запрос предварительной проверки запускается, а ответ сервера на этот запрос должен включать этот настраиваемый заголовок в режиме управления доступом -headers, установив его значение либо "*", либо имя пользовательского заголовка (x-request-with).

Надеюсь, что это немного улучшится.

Ответ 5

Во-первых, для решения вашей главной проблемы можно сделать запрос CORS при сохранении заголовка ajax?: ответ ДА, при условии, что сайты, к которым вы обращаетесь, разрешают запросы от вас или любого другого внешнего клиентов.

Вы писали:

//Note: this disables CORS
$httpProvider.defaults.headers.common["X-Requested-With"] = 'XMLHttpRequest';

Но я не понимаю, что вы подразумеваете под этим, это "отключает CORS". Заголовок X-Requested-With не является стандартным заголовком, и известный эффект добавления нестандартного заголовка в запрос (сделанный из браузера) - это запуск предполетного запроса [3].

Если другие сайты, которые вас интересуют, заставят их серверы отказываться от обработки запросов, которые не происходят из их собственного домена, то, задаете ли вы этот заголовок или нет, ваш запрос должен завершиться неудачей.

Кажется, что все отлично работает для вас, для запросов, отправленных на ваш собственный сервер. В противном случае вы можете решить проблему, добавив заголовок Access-Control-Allow-Origin в ответе сервера следующим образом:

  • если вам нужно разрешить запросы из определенных доменов

    response.set("Access-Control-Allow-Origin", "one-host-domain, your-host-domain, some-other-host-domain"); // second argument is a comma-delimited list of allowed domains

    (Возможно, вам лучше проверить объект запроса для источника, и если он разрешен на основе наличия в предварительно определенном списке, тогда отправьте обратно то же самое происхождение).

  • Если вам нужно разрешить все запросы независимо от их происхождения

    response.set("Access-Control-Allow-Origin", "*");

Это должно сделать, и я надеюсь, что это очистит ваши сомнения для вас.

Дополнительная информация по обработке CORS при использовании AJAX: 0, 1 и 2.


ИЗМЕНИТЬ

После обмена комментариями я добавлю следующие пункты, чтобы поддержать этот ответ далее.

Как и сегодня, единственной стороной, которая нуждается в отключении/включении CORS в системе клиент-сервер, является сервер. Все современные браузеры позволяют по умолчанию запрашивать запросы по кросс-контенту, и вам не нужно ничего делать для поддержки этой возможности. Я понял, что вы добавляете настраиваемый заголовок, чтобы отличать запросы AJAX от остальных? AFAIK, этот заголовок ничего не меняет о том, как выполняются запросы браузерами.

Вот как все запросы перекрестного происхождения обрабатываются браузерами сегодня: для всех методов запросов (но обычно, за исключением GET) браузеры отправляют запрос перед полетом с помощью OPTION. Если сервер назначения разрешает его, тогда отправляется фактический запрос, в противном случае запрос терпит неудачу. В случае, когда серверы отвечают с отказом, вы ничего не можете использовать ни в какой библиотеке, которую вы используете. Это факт из моего собственного опыта.