Предварительное поле CORS возвращается с Access-Control-Allow-Origin: *, браузер все еще не выполняет запрос

Запуск AJAX GET до http://qualifiedlocalhost:8888/resource.json запускает ожидаемый предварительный полет CORS, который выглядит так, как будто он возвращается правильно:

Запрос перед полетом OPTIONS

Request URL:http://qualifiedlocalhost:8888/resource.json
Request Method:OPTIONS
Status Code:200 OK

Заголовок запроса

Accept:*/*
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8
Access-Control-Request-Headers:accept, origin, x-requested-with
Access-Control-Request-Method:GET
Cache-Control:no-cache
Connection:keep-alive
Host:qualifiedlocalhost:8888
Origin:http://localhost:9000
Pragma:no-cache
Referer:http://localhost:9000/
User-Agent:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.71 Safari/537.36

Заголовки ответов

Access-Control-Allow-Headers:Content-Type, X-Requested-With
Access-Control-Allow-Methods:GET,PUT,POST,DELETE
Access-Control-Allow-Origin:*
Connection:keep-alive
Content-Length:2
Content-Type:text/plain
Date:Thu, 01 Aug 2013 19:57:43 GMT
Set-Cookie:connect.sid=s%3AEpPytDm3Dk3H9V4J9y6_y-Nq.Rs572s475TpGhCP%2FK%2B2maKV6zYD%2FUg425zPDKHwoQ6s; Path=/; HttpOnly
X-Powered-By:Express

Хорошо выглядеть?

Итак, он должен работать, правильно?

Но последующий запрос все еще не выполняется с ошибкой XMLHttpRequest cannot load http://qualifiedlocalhost:8888/resource.json. Origin http://localhost:9000 is not allowed by Access-Control-Allow-Origin.

Истинный запрос

Request URL:http://qualifiedlocalhost:8888/resource.json

Заголовок запроса

Accept:application/json, text/plain, */*
Cache-Control:no-cache
Origin:http://localhost:9000
Pragma:no-cache
Referer:http://localhost:9000/
User-Agent:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.71 Safari/537.36
X-Requested-With:XMLHttpRequest

Помогите!

Может быть, он смотрит прямо передо мной. Но какие-нибудь идеи? На всякий случай это актуально... Я использую AngularJS $resource и разговариваю с CompoundJS-сервером.

Ответы

Ответ 1

измените свои методы управления доступом-Allow: "GET, POST" для "GET, POST, PUT, DELETE"

перед:

   app.use(function(req, res, next) {
        res.setHeader('Access-Control-Allow-Origin', '*');
        res.setHeader('Access-Control-Allow-Methods', 'GET, POST');
        res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type, Authorization');
        next();
    });

После:

app.use(function(req, res, next) {
    res.setHeader('Access-Control-Allow-Origin', '*');
    res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT ,DELETE');
    res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type, Authorization');
    next();
});

Ответ 2

Является ли ваш веб-сервер/функция get ТАКЖЕ, включая HTTP-заголовок: Access-Control-Allow-Origin? В итоге я нашел успех с этим дополнением, используя AngularJS 1.0.7 и удаленный Java-сервлет. Вот мой фрагмент кода Java - никаких изменений в клиенте AngularJS не было:

Servlet:

@Override
protected void doOptions(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    // Send Response
    super.doOptions(request,  response);
    response.setHeader("Access-Control-Allow-Origin", "*");
    response.setHeader("Access-Control-Allow-Headers", "Content-Type, X-Requested-With");
}

@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    /* ... */
    response.setHeader("Access-Control-Allow-Origin", "*");
}

Более элегантной альтернативой является фильтр сервлетов.

Ответ 3

I недавно была та же проблема. Проблема в том, что заголовок Access-Control-Allow-Origin (и, если вы используете его, заголовок Access-Control-Allow-Credentials) должен быть отправлен в и ответ перед полетом и фактический ответ.

В вашем примере это будет только в предполетном ответе.

Ответ 4

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

Теория работы...

Очистка кеша браузера решает проблему в нашем случае. Моя нынешняя рабочая теория заключается в том, что это связано с тем, что файлы cookie устанавливаются сервером кросс-исходного кода. Я заметил, что в вашем сценарии есть файл cookie, который устанавливается как часть ответа на запрос перед полетом OPTIONS. Вы пытались заставить сервер не устанавливать файлы cookie для запросов, поступающих из другого источника?

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

Для справки, вот мой сценарий (я почти разместил это как новый вопрос в SO, но вместо этого поставил его здесь):

Мы столкнулись с ошибкой, когда некоторые запросы CORS GET, выполненные с помощью jQuery.ajax, терпели неудачу. В данном сеансе браузера мы видим запрос перед полетом OPTIONS, за которым следует фактический запрос. На той же сессии некоторые запросы проходят, а другие терпят неудачу.

Последовательность запросов и ответов в сетевой консоли браузера выглядит следующим образом:

Сначала предварительный запрос OPTIONS

OPTIONS /api/v1/users/337/statuses
HTTP/1.1 Host: api.obfuscatedserver.com 
Connection: keep-alive 
Access-Control-Request-Method: GET 
Origin: http://10.10.8.84:3003 
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36
Access-Control-Request-Headers: accept, origin, x-csrf-token, auth 
Accept: */* Referer: http://10.10.8.84:3003/ 
Accept-Encoding: gzip,deflate,sdch Accept-Language: en-US,en;q=0.8

Что получает ответ вроде:

HTTP/1.1 200 OK 
Date: Tue, 06 Aug 2013 19:18:22 GMT 
Server: Apache/2.2.22 (Ubuntu) 
Access-Control-Allow-Origin: http://10.10.8.84:3003 
Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT 
Access-Control-Max-Age: 1728000 
Access-Control-Allow-Credentials: true 
Access-Control-Allow-Headers: accept, origin, x-csrf-token, auth 
X-UA-Compatible: IE=Edge,chrome=1 
Cache-Control: no-cache 
X-Request-Id: 4429c4ea9ce12b6dcf364ac7f159c13c 
X-Runtime: 0.001344 
X-Rack-Cache: invalidate, pass 
X-Powered-By: Phusion 
Passenger 4.0.2 
Status: 200 OK 
Vary: Accept-Encoding
Content-Encoding: gzip

Затем фактический запрос GET,

GET https://api.obfuscatedserver.com/api/v1/users/337
HTTP/1.1 
Accept: application/json, text/javascript, */*; q=0.01 
Referer: http://10.10.8.84:3003/ 
Origin: http://10.10.8.84:3003 
X-CSRF-Token: xxxxxxx 
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36 
auth: xxxxxxxxx

Что вызывает ошибку в консоли браузера, например,

XMLHttpRequest
  cannot load https://api.obfuscatedserver.com/api/v1/users/337.
  Origin http://10.10.8.84:3003 is not allowed by Access-Control-Allow-Origin.

Дополнительная отладка

Я могу воспроизвести одну и ту же последовательность с помощью curl, и я вижу действительные ответы, поступающие с сервера. то есть у них есть ожидаемые заголовки CORS, которые должны пропускать запросы.

Выполнение того же сценария в окне браузера in-private/incognito не воспроизводило проблему. Это заставило меня попробовать очистить кеш, и это заставило проблему уйти. Но через некоторое время он вернулся.

Проблема воспроизводилась на iPhone Safari, а также на Chrome на рабочем столе OSX.

Что мне действительно нужно с помощью

Я подозреваю, что в домене кросс-происхождения есть несколько файлов cookie, которые здесь участвуют и потенциально могут выявить ошибку в браузере. Есть ли инструменты или точки останова, которые я могу установить в браузере (собственный стек?), Чтобы попробовать и отладить это дальше? Точка останова в коде, которая оценивает политику CORS, была бы идеальной.

Ответ 5

Похоже, ваш ответ на "параметры" работает нормально. Проблема, кажется, в ответе "получить" .

Вы хотите, чтобы ваш ответ "получить" возвращал те же заголовки CORS, что и ответ "options".

В частности, ответ "получить" должен включать

Access-Control-Allow-Headers:Content-Type, X-Requested-With
Access-Control-Allow-Methods:GET,PUT,POST,DELETE
Access-Control-Allow-Origin:*

Ответ 6

используйте модуль cors, чтобы избежать проблемы

var cors = require('cors')

var app = express()
app.use(cors())