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?
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
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.
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
Access-Control-Max-Age
pour la demande OPTIONUne demande intersite simple est une demande qui répond à toutes les conditions suivantes:
Les seules méthodes autorisées sont:
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:
Les seules valeurs autorisées pour l'en-tête Content-Type sont les suivantes:
Une simple demande ne provoquera pas une demande OPTION préalable au vol.
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.
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:
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
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).
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!
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.
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.
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.
Vous ne pouvez pas mais vous pouvez éviter CORS en utilisant JSONP.
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.