web-dev-qa-db-fra.com

Chrome annule CORS XHR lors de la redirection HTTP 302

Il semble que, conformément à CORS Spec , GET et POST doivent suivre en toute transparence les redirections 302). Mais Chrome annule ma requête) .

Voici le JS qui fait la demande:

var r = new XMLHttpRequest();
r.open('GET', 'https://dev.mysite.com/rest', true);
r.send();

Voici ce qui devrait arriver:

  1. Client: XHR POST demande à/reste
  2. Serveur: répond avec une redirection HTTP 302 vers/rest /
  3. Client: suivez cette redirection

Mais après l'étape 2, Chrome annule la demande. S'il n'y avait pas de HTTP 302, la demande fonctionnerait parfaitement. Je l'ai confirmé.

Lorsque la requête est exécutée, un seul XHR apparaît dans le panneau Réseau de Chrome: une requête annulée POST sans en-tête de réponse ni corps de réponse.

En déboguant avec l'outil net-internals de Chrome, je constate qu'une réponse a été envoyée par le serveur, puis la demande a été annulée. Voici le résultat de la requête:

79295: URL_REQUEST
https://dev.mysite.com/rest
Start Time: 2013-08-30 12:41:11.637

t=1377880871637 [st=    0] +REQUEST_ALIVE  [dt=13455]
t=1377880871638 [st=    1]    URL_REQUEST_BLOCKED_ON_DELEGATE  [dt=1]
                              --> delegate = "extension Adblock Plus"
t=1377880871639 [st=    2]   +URL_REQUEST_START_JOB  [dt=13453]
                              --> load_flags = 143540480 (DO_NOT_SAVE_COOKIES | DO_NOT_SEND_AUTH_DATA | DO_NOT_SEND_COOKIES | ENABLE_LOAD_TIMING | MAYBE_USER_GESTURE | REPORT_RAW_HEADERS | VERIFY_EV_CERT)
                              --> method = "POST"
                              --> priority = 2
                              --> upload_id = "0"
                              --> url = "https://dev.mysite.com/rest"
t=1377880871639 [st=    2]      HTTP_CACHE_GET_BACKEND  [dt=0]
t=1377880871639 [st=    2]     +HTTP_STREAM_REQUEST  [dt=7]
t=1377880871646 [st=    9]        HTTP_STREAM_REQUEST_BOUND_TO_JOB
                                  --> source_dependency = 79296 (HTTP_STREAM_JOB)
t=1377880871646 [st=    9]     -HTTP_STREAM_REQUEST
t=1377880871646 [st=    9]     +HTTP_TRANSACTION_SEND_REQUEST  [dt=0]
t=1377880871646 [st=    9]        HTTP_TRANSACTION_SEND_REQUEST_HEADERS
                                  --> GET /facultyportfolio-rest HTTP/1.1
                                      Host: dev.liberty.edu
                                      Connection: keep-alive
                                      Content-Length: 46
                                      Origin: http://localhost:8080
                                      User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.62 Safari/537.36
                                      Content-Type: application/json; charset=UTF-8
                                      Accept: */*
                                      Referer: http://localhost:8080/ajaxtest.html
                                      Accept-Encoding: gzip,deflate,sdch
                                      Accept-Language: en-US,en;q=0.8
t=1377880871646 [st=    9]        HTTP_TRANSACTION_SEND_REQUEST_BODY
                                  --> did_merge = true
                                  --> is_chunked = false
                                  --> length = 46
t=1377880871646 [st=    9]     -HTTP_TRANSACTION_SEND_REQUEST
t=1377880871646 [st=    9]     +HTTP_TRANSACTION_READ_HEADERS  [dt=1001]
t=1377880871646 [st=    9]        HTTP_STREAM_PARSER_READ_HEADERS  [dt=1000]
t=1377880872646 [st= 1009]        HTTP_TRANSACTION_READ_RESPONSE_HEADERS
                                  --> HTTP/1.1 302 Found
                                      Date: Fri, 30 Aug 2013 16:41:11 GMT
                                      Server: Apache/2
                                      Access-Control-Allow-Origin: http://localhost:8080
                                      Access-Control-Allow-Credentials: true
                                      Location: https://dev.mysite.com/rest/
                                      Content-Language: en-US
                                      Vary: Accept-Encoding,User-Agent
                                      Content-Encoding: gzip
                                      Content-Length: 20
                                      Connection: close
                                      Content-Type: text/plain; charset=UTF-8
t=1377880872647 [st= 1010]     -HTTP_TRANSACTION_READ_HEADERS
t=1377880872647 [st= 1010]     +URL_REQUEST_BLOCKED_ON_DELEGATE  [dt=12445]
t=1377880885091 [st=13454]        CANCELLED
t=1377880885092 [st=13455]   -URL_REQUEST_START_JOB
                              --> net_error = -3 (ERR_ABORTED)
t=1377880885092 [st=13455] -REQUEST_ALIVE

À la fin, vous pouvez voir "annulé" à cause de "URL_REQUEST_BLOCKED_ON_DELEGATE". Je ne sais pas ce que ça veut dire. Mais encore une fois, s'il n'y avait pas de redirection HTTP 302, l'erreur ne se produirait pas.

Est-ce que quelqu'un sait ce qui cause Chrome annuler cette demande?

44
Matthias Dailey

Les réponses ici sont mélangées, faisant allusion à certains paramètres de code, etc., ce qui peut résoudre le problème de redirection avec CORS, mais la spécification CORS spécifie clairement quand ces redirections échoueront/seront réussies: Selon la spécification, les navigateurs devraient

  1. Autorise la redirection 3XX si la demande adressée à la ressource redirigée ne nécessite pas de vérification avant le vol (demandes CORS simples sans en-tête personnalisé, par exemple). Voir https://www.w3.org/TR/cors/#simple-cross-Origin-request-

Si l'indicateur de redirection manuelle n'est pas défini et que la réponse a un code d'état HTTP de 301, 302, 303, 307 ou 308, appliquez les étapes de redirection.

  1. N'autorisez pas la redirection 3XX si la demande de ressource redirigée nécessite une vérification avant le vol. Voir https://www.w3.org/TR/cors/#cross-Origin-request-with-preflight-

Si la réponse a un code d'état HTTP de 301, 302, 303, 307 ou 308, appliquez les étapes de cache et d'erreur réseau.

J'ai exploré divers scénarios CORS dans le repo github: https://github.com/monmohan/cors-experiment .

Ce problème spécifique avec une redirection échouée peut également être facilement reproduit isolément par le bundle ici: https://github.com/monmohan/cors-experiment/tree/master/issue

22
factotum

J'ai trouvé cet article à propos de définir l'en-tête CORS Access-Control-Allow-Origin correct sur votre réponse 302 pour être utile, du moins dans mon cas similaire.

L'enquête sur le problème a montré que son XHR n'atteignait pas directement l'URL activée par CORS, mais y était redirigé via une réponse HTTP 302 (redirection).

Gardez donc à l'esprit que l'URL de redirection doit également inclure un en-tête Access-Control-Allow-Origin, sinon le navigateur s'arrêtera là avec sa tentative de requête inter-domaines.

Nous avons également constaté que la définition d'en-têtes CORS supplémentaires au-delà des limites d'accès-contrôle-autorisation-origine entraînait souvent l'annulation d'une transaction.

9
Josh Rosenblum

http://httpstatus.es/302

Si le code d'état 302 est reçu en réponse à une demande autre que GET ou HEAD, l'agent d'utilisateur NE DOIT PAS automatiquement rediriger la demande à moins que l'utilisateur puisse le confirmer, car cela pourrait modifier les conditions dans lesquelles la demande a été émise.

9
idbehold

J'ai également eu le problème que Chrome ne suivait pas une redirection sur une demande CORS. Pour moi, le problème était que le framework JS que j'utilise (Sencha Touch) ajoute un en-tête de demande: X-Requested -With: "XMLHttpRequest"

Dès que j'ai supprimé cela (dans Sencha Touch en appelant Ext.Ajax.setUseDefaultXhrHeader (false);) cela a fonctionné comme un charme.

Je ne sais pas pourquoi mais j'espère que cette information aidera quelqu'un.

2
Ronald