Pourquoi envoie-t-on une demande D'OPTIONS et puis-je la désactiver?
je construis une api web. J'ai trouvé que chaque fois que J'utilise Chrome pour poster, accéder à mon API, il y a toujours une requête D'OPTION envoyée avant la requête réelle, ce qui est assez ennuyeux. Actuellement, je reçois le serveur d'Ignorer toutes les requêtes D'OPTIONS. Maintenant, mes questions sont ce qui est bon d'envoyer une requête D'OPTION pour doubler la charge du serveur? Y a-t-il un moyen d'empêcher complètement le navigateur d'envoyer des requêtes D'OPTIONS?
15 réponses
edit 2018-09-13 : ajout de quelques précisions sur cette demande pré-vol et comment l'éviter à la fin de cette réponse.
OPTIONS
les requêtes sont ce que nous appelons pre-flight
les requêtes dans Cross-origin resource sharing (CORS)
.
ils sont nécessaires lorsque vous faites des demandes à travers différentes origines dans des situations spécifiques.
cette demande pré-vol est faite par certains navigateurs à titre de mesure de sécurité pour assurer que la requête en cours est approuvé par le serveur. Sens le serveur comprend que la méthode, l'origine et les en-têtes envoyés sur la demande sont sans danger pour agir.
votre serveur ne doit pas ignorer mais traiter ces requêtes chaque fois que vous tentez de faire des requêtes d'origine croisée.
une bonne ressource peut être trouvé ici http://enable-cors.org /
une façon de les manipuler pour être à l'aise est pour s'assurer que pour n'importe quel chemin avec 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 requêtes de n'importe quelle origine.
pour plus d'informations sur la façon d'ajouter le support CORS à votre serveur, consultez l'organigramme suivant
http://www.html5rocks.com/static/images/cors_server_flowchart.png
edit 2018-09-13
CORS OPTIONS
demande est déclenché uniquement dans certains cas, comme expliqué dans MDN docs :
Some requests don’t trigger a CORS preflight. Those are called “simple requests” in this article, though the Fetch spec (which defines CORS) doesn’t use that term. A request that doesn’t trigger a CORS preflight—a so-called “simple request”—is one that meets all the following conditions:
The only allowed methods are:
- GET
- HEAD
- POST
Apart from the headers set automatically by the user agent (for example, Connection, User-Agent, or any of the other headers with names defined in the Fetch spec as a “forbidden header name”), the only headers which are allowed to be manually set are those which the Fetch spec defines as being a “CORS-safelisted request-header”, which are:
- Accept
- Accept-Language
- Content-Language
- Content-Type (but note the additional requirements below)
- DPR
- Downlink
- Save-Data
- Viewport-Width
- Width
The only allowed values for the Content-Type header are:
- application/x-www-form-urlencoded
- multipart/form-data
- text/plain
No event listeners are registered on any XMLHttpRequestUpload object used in the request; these are accessed using the XMLHttpRequest.upload property.
No ReadableStream object is used in the request.
s'il vous Plaît consulter cette réponse sur le besoin réel de pré-flighted demande OPTIONS: de la SCRO - Quelle est la motivation derrière l'introduction du contrôle en amont des demandes?
pour désactiver la requête OPTIONS, les conditions ci-dessous doivent être remplies pour la requête ajax:
- Demande de ne pas définir des en-têtes HTTP personnalisés comme "application/xml" ou "application/json" etc
- la méthode request doit être une de GET, De la TÊTE ou par la POSTE. Si le POST, un type de contenu doit être l'un des
application/x-www-form-urlencoded
,multipart/form-data
, outext/plain
référence: https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
ont traversé cette question, ci-dessous est ma conclusion à cette question et ma solution.
selon la CORS strategy (fortement recommandé de lire à ce sujet), vous ne pouvez pas juste forcer le navigateur à cesser d'envoyer la demande D'OPTION s'il pense qu'il a besoin.
il y a deux façons de travailler
-
- assurez-vous que votre demande est une " simple demande"
-
- Set
Access-Control-Max-Age
pour l'OPTION "demande de 1519140920"
- Set
Simple requête
une simple demande trans-site est une demande qui remplit toutes les conditions suivantes:
les seules méthodes autorisées sont: - OBTENIR - TÊTE - POST
à L'exclusion des en-têtes configurés automatiquement par l'agent utilisateur (par exemple connexion, User-Agent, etc.), les seuls en-têtes qui peuvent être réglés manuellement sont: - Accepter - Accept-Language - Contenu-Langue - Type De Contenu
les seules valeurs autorisées pour l'en-tête Content-Type sont: - application / x-www-form-urlencoded - multipart / form-data - text /plain
une simple demande ne donnera pas lieu à une demande d'OPTION pré-vol.
définit un cache pour le contrôle D'OPTION
vous pouvez définir un Access-Control-Max-Age
pour l'OPTION de demande, de sorte qu'il ne vérifiera pas la permission de nouveau jusqu'à ce qu'il est expiré.
contrôle D'accès-max-Age donne la valeur en secondes pour combien de temps la réponse à la demande pré-vol peut être mise en cache sans envoyer une autre demande pré-vol.
Oui il est possible d'éviter les requêtes d'options. La demande d'Options est une demande pré-vol lorsque vous envoyez (post) 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 de CORS et d'utiliser la solution readymade et il fonctionnera n'importe où.
Regardez ici: https://github.com/jpillora/xdomain
et de travail exemple: http://jpillora.com/xdomain /
bonne journée!
lorsque la console de débogage est ouverte et que l'option Disable Cache
est activée, les requêtes avant vol seront toujours envoyées (c'est-à-dire avant chaque requête). si vous ne désactivez pas le cache, une requête pré-vol ne sera envoyée qu'une seule fois (par serveur)
comme mentionné dans les billets précédents déjà, OPTIONS
requêtes sont là pour une raison. Si vous avez un problème avec les temps de réponse élevés de votre serveur (par exemple connexion à l'étranger), vous pouvez également avoir votre cache de navigateur les requêtes pré-Lig niques.
faites répondre votre serveur avec l'en-tête Access-Control-Max-Age
et pour les requêtes qui vont au même endpoint, la requête preflight aura été mise en cache et ne se produira plus.
pour un développeur qui comprend la raison pour laquelle il existe, mais qui a besoin d'accéder à une API qui ne gère pas les appels D'OPTIONS sans autorisation, j'ai besoin d'une réponse temporaire afin de pouvoir développer localement jusqu'à ce que le propriétaire de L'API ajoute le support approprié de L'API CORS ou que j'obtienne une API proxy qui démarre.
j'ai trouvé que vous pouvez désactiver CORS en Safari et Chrome sur un Mac.
Désactiver la même origine dans Chrome
Chrome: Quit Chrome, ouvrir un terminal et coller cette commande: open /Applications/Google\ Chrome.app --args --disable-web-security --user-data-dir
Safari: la Désactivation de l'origine de la politique dans Safari
si vous voulez désactiver la Politique de même origine sur Safari (j'ai 9.1.1), alors vous n'avez qu'à activer le menu developer, et sélectionner" Désactiver les Restrictions D'origine croisée " dans le menu develop.
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();
}
il est seulement pour le développement. Avec ceci j'attends 9ms et 500ms et pas 8s et 500ms. Je peux le faire parce que production js app sera sur la même machine que la production donc il n'y aura pas de OPTIONS
mais le développement est mon local.
vous ne pouvez pas mais vous pouvez éviter les CORS en utilisant JSONP.
après avoir passé une journée et demie à essayer de résoudre un problème similaire, j'ai trouvé qu'il avait à voir avec 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 les options de configuration sur le web.config > système.noeud webServer comme j'ai vu dans tant de messages
pas de code spécifique CORS dans le global.asax ou dans le contrôleur en tant que décorateur
, le problème était Le application des paramètres du pool .
le managed pipeline mode a été mis à la classique ( l'a changé à Intégré ) et le identité a été mis au service de réseau ( l'a changé à ApplicationPoolIdentity )
changer ces paramètres (et rafraîchir l'application la piscine), il fixe pour moi.
ce qui a fonctionné pour moi était d'importer "github.com/gorilla/handlers "et puis l'utiliser de cette façon:
router := mux.NewRouter()
router.HandleFunc("/config", getConfig).Methods("GET")
router.HandleFunc("/config/emcServer", createEmcServers).Methods("POST")
headersOk := handlers.AllowedHeaders([]string{"X-Requested-With", "Content-Type"})
originsOk := handlers.AllowedOrigins([]string{"*"})
methodsOk := handlers.AllowedMethods([]string{"GET", "HEAD", "POST", "PUT", "OPTIONS"})
log.Fatal(http.ListenAndServe(":" + webServicePort, handlers.CORS(originsOk, headersOk, methodsOk)(router)))
dès que j'exécutais une requête Ajax POST et y attachais des données JSON, Chrome ajoutait toujours l'en-tête Content-Type qui n'était pas dans ma précédente configuration AllowedHeaders.
je pense, vous envoyez une demande à cross domain .
Pour cross-domain "151930920 les demandes", le réglage du type de contenu à autre chose que application / x-www-form-urlencoded , multipart/form-data , ou text / plain va déclencher le navigateur pour envoyer un Preflight OPTIONS demande au serveur.
ainsi vous pouvez avoir besoin de spécifier contentType pour éviter la requête D'OPTION.
Exemple De Jquery: -
$.ajax({
url: "http://crossdomainurl",
type: "POST",
contentType: 'text/plain'
});
il y a peut-être une solution (mais je ne l'ai pas testé) : vous pouvez utiliser CSP (Content Security Policy) pour activer votre domaine distant et les navigateurs sauteront peut-être la vérification des requêtes D'OPTIONS CORS.
si je trouver un peu de temps, je vais tester ça et mise à jour de ce post !
CSP: https://developer.mozilla.org/fr/docs/Web/HTTP/Headers/Content-Security-Policy
Spécification CSP: https://www.w3.org/TR/CSP /
une solution que j'ai utilisée dans le passé - disons que votre site est sur mydomain.com, et vous devez faire une demande ajax pour foreigndomain.com
configurer une réécriture IIS de votre domaine vers le domaine étranger-e.g.
<rewrite>
<rules>
<rule name="ForeignRewrite" stopProcessing="true">
<match url="^api/v1/(.*)$" />
<action type="Rewrite" url="https://foreigndomain.com/{R:1}" />
</rule>
</rules>
</rewrite>
sur votre mydomain.com site - vous pouvez alors faire une même demande d'origine, et il n'y a pas besoin de demande d'options:)
il peut être résolu en cas d'utilisation d'un proxy qui intercepte la requête et écrit les en-têtes appropriés. Dans le cas particulier du vernis ce serait les règles:
if (req.http.host == "CUSTOM_URL" ) {
set resp.http.Access-Control-Allow-Origin = "*";
if (req.method == "OPTIONS") {
set resp.http.Access-Control-Max-Age = "1728000";
set resp.http.Access-Control-Allow-Methods = "GET, POST, PUT, DELETE, PATCH, OPTIONS";
set resp.http.Access-Control-Allow-Headers = "Authorization,Content-Type,Accept,Origin,User-Agent,DNT,Cache-Control,X-Mx-ReqToken,Keep-Alive,X-Requested-With,If-Modified-Since";
set resp.http.Content-Length = "0";
set resp.http.Content-Type = "text/plain charset=UTF-8";
set resp.status = 204;
}
}