web-dev-qa-db-fra.com

Pourquoi une demande OPTIONS est-elle envoyée et puis-je la désactiver?

Je construis une API Web. J'ai constaté que chaque fois que j'utilise Chrome pour POST, GET pour mon API, il y a toujours une demande OPTIONS envoyée avant la demande réelle, ce qui est assez gênant. Actuellement, je demande au serveur d’ignorer toutes les demandes d’OPTIONS. Ma question est la suivante: pourquoi envoyer une demande OPTIONS pour doubler la charge du serveur? Existe-t-il un moyen d'empêcher complètement le navigateur d'envoyer des requêtes OPTIONS? 

271
Elgs Qian Chen

edit 2018-09-13: ajout de précisions sur cette demande de pré-vol et sur la manière de l'éviter à la fin de cette réponse.

Les demandes OPTIONS sont ce que nous appelons les demandes pre-flight dans Cross-Origin resource sharing (CORS).

Ils sont nécessaires lorsque vous faites des demandes de différentes origines dans des situations spécifiques. 

Certains navigateurs font cette demande avant le vol par mesure de sécurité pour s'assurer que la demande en cours de traitement est approuvée par le serveur. Cela signifie que le serveur comprend que la méthode, l'origine et les en-têtes envoyés sur la requête sont sûrs. 

Votre serveur ne doit pas ignorer mais gérer ces requêtes à chaque fois que vous tentez de faire des requêtes croisées avec Origin.

Une bonne ressource peut être trouvée ici http://enable-cors.org/

Une façon de les gérer est de s’assurer que, pour tout chemin utilisant la méthode OPTIONS, le serveur envoie une réponse avec cet en-tête. 

Access-Control-Allow-Origin: *

Cela indiquera au navigateur que le serveur est prêt à répondre aux demandes de n'importe quelle origine. 

Pour plus d'informations sur l'ajout de la prise en charge de CORS à votre serveur, voir l'organigramme suivant.

http://www.html5rocks.com/static/images/cors_server_flowchart.png

CORS Flowchart


edit 2018-09-13

La demande CORS OPTIONS n'est déclenchée que dans certains cas, comme expliqué dans Documents MDN :

Certaines demandes ne déclenchent pas de contrôle en amont CORS. Celles-ci sont appelées «demandes simples» dans cet article, bien que la spécification Fetch (qui définit CORS) n’utilise pas ce terme. Une demande qui ne déclenche pas de contrôle en amont CORS, appelée «demande simple», remplit toutes les conditions suivantes:

Les seules méthodes autorisées sont:

  • GET
  • HEAD
  • POST

Outre les en-têtes définis automatiquement par l'agent d'utilisateur (par exemple, Connection, User-Agent ou l'un des autres en-têtes dont le nom est défini dans la spécification Fetch en tant que «nom d'en-tête interdit»), les seuls en-têtes autorisés sont définies manuellement celles que la spécification Fetch définit comme étant un "en-tête de demande protégé par CORS", à savoir:

  • Acceptez
  • Accepter la langue
  • Contenu-Langue
  • Content-Type (mais notez les exigences supplémentaires ci-dessous)
  • DPR
  • Liaison descendante
  • Enregistrer des données
  • Largeur de la fenêtre
  • Largeur

Les seules valeurs autorisées pour l'en-tête Content-Type sont les suivantes:

  • application/x-www-form-urlencoded
  • multipart/form-data
  • texte simple

Aucun écouteur d'événement n'est inscrit sur un objet XMLHttpRequestUpload utilisé dans la demande. ces derniers sont accessibles à l'aide de la propriété XMLHttpRequest.upload.

Aucun objet ReadableStream n'est utilisé dans la demande.

256
Leo Correa

Nous avons parcouru ce problème. Voici ma conclusion et la solution proposée.

Selon la stratégie CORS (nous vous recommandons vivement de lire cette information). Vous ne pouvez pas simplement forcer le navigateur à cesser d’envoyer une demande OPTION s’il le juge nécessaire. 

Il y a deux façons de contourner le problème

    1. Assurez-vous que votre demande est une "demande simple"
    1. Définir Access-Control-Max-Age pour la demande OPTION

Demande simple

Une demande intersite simple est une demande qui répond à toutes les conditions suivantes:

Les seules méthodes autorisées sont:

  • GET
  • HEAD
  • POST

Outre les en-têtes définis automatiquement par l'agent utilisateur (par exemple, Connexion, Agent utilisateur, etc.), les seuls en-têtes autorisés à être définis manuellement sont les suivants:

  • Acceptez
  • Accepter la langue
  • Contenu-Langue
  • Type de contenu

Les seules valeurs autorisées pour l'en-tête Content-Type sont les suivantes:

  • application/x-www-form-urlencoded
  • multipart/form-data
  • texte simple

Une simple demande ne provoquera pas une demande OPTION préalable au vol.

Définir un cache pour la vérification OPTION

Vous pouvez définir un Access-Control-Max-Age pour la demande OPTION afin qu'il ne vérifie plus l'autorisation avant son expiration.

Access-Control-Max-Age donne la valeur en secondes pour combien de temps la réponse à la demande de contrôle en amont peut être mise en cache sans envoyer une autre demande de contrôle en amont.

133
Neekey

Veuillez vous référer à cette réponse concernant le besoin réel de demande OPTIONS pré-enregistrée: CORS - Quelle est la motivation qui pousse à introduire des demandes de contrôle en amont?

Pour désactiver la demande OPTIONS, les conditions ci-dessous doivent être satisfaites pour la demande ajax:

  1. La requête ne définit pas les en-têtes HTTP personnalisés tels que "application/xml" ou "application/json", etc.
  2. La méthode de requête doit être GET, HEAD ou POST. Si POST, le type de contenu doit être l'un des application/x-www-form-urlencoded, multipart/form-data ou text/plain

Référence: https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS

132
device_exec

Lorsque la console de débogage est ouverte et que l'option Disable Cache est activée, les demandes de contrôle en amont sont toujours envoyées (c'est-à-dire avant chaque demande). si vous ne désactivez pas le cache, une demande de pré-vol ne sera envoyée qu'une fois (par serveur).

40
Nir

Oui, il est possible d'éviter la demande d'options. La requête d'options est une requête de contrôle en amont lorsque vous envoyez (publiez) des données à un autre domaine. C'est un problème de sécurité du navigateur. Mais nous pouvons utiliser une autre technologie: la couche de transport iframe. Je vous recommande fortement d'oublier toute configuration CORS et d'utiliser une solution readymade. Elle fonctionnera n'importe où. 

Jetez un oeil ici: https://github.com/jpillora/xdomain

Et exemple de travail: http://jpillora.com/xdomain/

Bonne journée!

38
user889349

Comme mentionné dans les messages précédents, les demandes OPTIONS sont là pour une raison. Si vous rencontrez un problème de temps de réponse important de votre serveur (par exemple, connexion à l'étranger), vous pouvez également demander à votre navigateur de mettre en cache les demandes de contrôle en amont.

Demandez à votre serveur de répondre avec l'en-tête Access-Control-Max-Age et pour les demandes adressées au même noeud final, la demande de contrôle en amont aura été mise en cache et ne se produira plus.

14
enpenax

Pour un développeur qui comprend la raison de son existence mais qui doit accéder à une API qui ne gère pas les appels OPTIONS sans autorisation, j'ai besoin d'une réponse temporaire pour pouvoir développer localement jusqu'à ce que le propriétaire de l'API ajoute la prise en charge appropriée de SPA CORS ou que je reçoive une API proxy opérationnel. 

J'ai trouvé que vous pouvez désactiver CORS dans Safari et Chrome sur un Mac.

Désactiver la même stratégie d'origine dans Chrome

Chrome: quittez Chrome, ouvrez un terminal et collez cette commande: open /Applications/Google\ Chrome.app --args --disable-web-security --user-data-dir

Safari: Désactivation de la stratégie d’origine identique dans Safari

Si vous souhaitez désactiver la politique de même origine sur Safari (version 9.1.1), vous devez uniquement activer le menu du développeur et sélectionner "Désactiver les restrictions d'origine croisée" dans le menu de développement.

12
Joseph Juhnke

J'ai résolu ce problème comme.

if($_SERVER['REQUEST_METHOD'] == 'OPTIONS' && ENV == 'devel') {
    header('Access-Control-Allow-Origin: *');
    header('Access-Control-Allow-Headers: X-Requested-With');
    header("HTTP/1.1 200 OK");
    die();
}

C'est seulement pour le développement. Avec cela, j'attends 9ms et 500ms et pas 8s et 500ms. Je peux le faire parce que l'application JS de production sera sur la même machine que la production, il n'y aura donc pas de OPTIONS mais le développement est mon local.

6
AntiCZ

Vous ne pouvez pas mais vous pouvez éviter CORS en utilisant JSONP.

5
Jose Mato

Après avoir passé une journée et demie à essayer de résoudre un problème similaire, j’ai trouvé que c’était lié àIIS

Mon projet d'API Web a été configuré comme suit:

// WebApiConfig.cs
public static void Register(HttpConfiguration config)
{
    var cors = new EnableCorsAttribute("*", "*", "*");
    config.EnableCors(cors);
    //...
}

Je n'avais pas d'options de configuration spécifiques à CORS dans le nœud web.config> system.webServer, comme je l'ai vu dans de nombreux messages

Aucun code spécifique CORS dans le fichier global.asax ou dans le contrôleur en tant que décorateur

Le problème était les paramètres de la piscine app

Le mode de pipeline managed a été défini sur classique (l'a changé en intégration) et l'identitéa été défini sur Service réseau (l'a modifié en ApplicationPoolIdentity).

La modification de ces paramètres (et l'actualisation du pool d'applications) a résolu le problème pour moi.

0
Ju66ernaut