web-dev-qa-db-fra.com

AJAX dans Chrome envoi d'OPTIONS au lieu de GET / POST / PUT / DELETE?

Je travaille sur une application Web interne au travail. Dans IE10, les requêtes fonctionnent correctement, mais dans Chrome, toutes les requêtes AJAX (qui sont nombreuses) sont envoyées à l'aide d'OPTIONS et non de la méthode définie que je leur donne. Techniquement, mes demandes sont "interdomaines". Le site est servi sur localhost: 6120 et le service auquel je fais AJAX demander est sur 57124. Ce bogue jQuery fermé définit le problème, mais pas un vrai correctif.

Que puis-je faire pour utiliser la méthode http appropriée dans les requêtes ajax?

Modifier:

C'est dans le chargement de document de chaque page:

jQuery.support.cors = true;

Et chaque AJAX est construit de la même manière:

var url = 'http://localhost:57124/My/Rest/Call';
$.ajax({
    url: url,
    dataType: "json",
    data: json,
    async: true,
    cache: false,
    timeout: 30000,
    headers: { "x-li-format": "json", "X-UserName": userName },
    success: function (data) {
        // my success stuff
    },
    error: function (request, status, error) {
        // my error stuff
    },
    type: "POST"
});
99
Corey Ogburn

Chrome contrôle en amont la requête pour rechercher les en-têtes CORS . Si la demande est acceptable, il enverra alors la demande réelle. Si vous faites ce domaine, vous devrez simplement vous en occuper ou bien trouver un moyen de rendre la demande non-domaine. C'est pourquoi le bogue jQuery a été fermé car rien ne sera corrigé. C'est par conception.

Contrairement aux requêtes simples (décrites ci-dessus), les requêtes "pré-contrôlées" envoient d'abord une requête HTTP par la méthode OPTIONS à la ressource de l'autre domaine, afin de déterminer si la requête réelle peut être envoyée en toute sécurité. Les requêtes intersites font l’objet d’un contrôle en amont de la sorte car elles peuvent avoir des conséquences sur les données de l’utilisateur. En particulier, une demande est contrôlée en amont si:

  • Il utilise des méthodes autres que GET, HEAD ou POST. De même, si POST est utilisé pour envoyer des données de demande avec un type de contenu autre que application/x-www-form-urlencoded, multipart/form-data ou text/plain, par exemple. si la demande POST envoie une charge XML au serveur à l'aide de application/xml ou text/xml, la demande est soumise à un contrôle en amont.
  • Il définit des en-têtes personnalisés dans la demande (par exemple, la demande utilise un en-tête tel que X-PINGOTHER).
128
Dark Falcon

Sur la base du fait que la demande n'est pas envoyée sur le port par défaut 80/443, cet appel Ajax est automatiquement considéré comme une demande de ressource ORC, ce qui signifie en d'autres termes que la demande est automatiquement émet une demande OPTIONS qui recherche les en-têtes CORS du côté du serveur/servlet.

Cela se produit même si vous définissez

crossOrigin: false;

ou même si vous l'omettez.

La raison en est simplement que localhost != localhost:57124. Essayez de l’envoyer uniquement à localhost sans le port - cela échouera, car la cible demandée ne sera pas accessible, notez cependant que si les noms de domaine sont égaux, la demande est envoyée sans le OPTIONS demande avant le POST.

16
Dropout

Je suis d'accord avec Kevin B, le rapport de bogue dit tout. On dirait que vous essayez de faire des appels ajax entre domaines. Si vous ne connaissez pas la même stratégie d'origine, vous pouvez commencer ici: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Same_Origin_policy_for_JavaScript .

S'il ne s'agit pas d'un appel ajax interdomaine, essayez de définir votre URL cible et de voir si le problème disparaît. Si vous êtes vraiment désespéré, jetez un coup d'œil au JSONP, mais attention, le chaos se cache. Nous ne pouvons vraiment pas faire plus pour vous aider.

3
jgitter

Dans mon cas, j'appelle une API hébergée par AWS (API Gateway). L'erreur s'est produite lorsque j'ai essayé d'appeler l'API à partir d'un domaine autre que le domaine de l'API. Depuis que je suis le propriétaire de l'API, j'ai activé CORS pour l'environnement de test, comme décrit dans Amazon Documentation .

En production, cette erreur ne se produira pas, car la requête et l'API seront dans le même domaine.

J'espère que ça aide!

1
gbonesso

Si cela est possible, transmettez les paramètres à GET/POST classique avec un nom différent et laissez le code côté serveur le gérer.

J'ai eu un problème similaire avec mon propre proxy pour contourner CORS et j'ai eu la même erreur de POST-> OPTION dans Chrome. C'était l'en-tête Authorization dans mon cas ("x-li-format" et "X-UserName" ici dans votre cas.) J'ai fini par le passer dans un format factice (par exemple AuthorizatinJack dans GET) et J'ai changé le code de mon mandataire pour en faire un en-tête lors de l'appel vers la destination. La voici en PHP:

if (isset($_GET['AuthorizationJack'])) {
    $request_headers[] = "Authorization: Basic ".$_GET['AuthorizationJack'];
}
1
Aidin

Les requêtes "pré-contrôlées" envoient d’abord une requête HTTP par la méthode OPTIONS à la ressource de l’autre domaine, afin de déterminer si la requête réelle peut être envoyée en toute sécurité. Requêtes inter-sites

https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS

0
Noorullah

J'ai rencontré un problème très similaire. J'ai passé presque une demi-journée à comprendre pourquoi tout fonctionnait correctement dans Firefox et échouait dans Chrome. Dans mon cas, c'était à cause de champs dupliqués (ou peut-être mal typés) dans l'en-tête de ma demande.

0
Andrew Tatomyr

Comme répond par @Dark Falcon, I l'a simplement traité .

Dans mon cas, j'utilise le serveur node.js et crée une session si elle n'existe pas. Comme la méthode OPTIONS ne contient pas les détails de la session, elle a fini par créer une nouvelle session pour chaque demande de méthode POST.

Donc, dans ma routine d'application pour créer-session-si-pas-exister, j'ai simplement ajouté une vérification pour voir si la méthode est OPTIONS, et si c'est le cas, ignorez simplement le composant de création de session:

    app.use(function(req, res, next) {
        if (req.method !== "OPTIONS") {
            if (req.session && req.session.id) {
                 // Session exists
                 next();
            }else{
                 // Create session
                 next();
          }
        } else {
           // If request method is OPTIONS, just skip this part and move to the next method.
           next(); 
        }
    }
0
Mahesh

Pensez à utiliser axios

axios.get( url,
{ headers: {"Content-Type": "application/json"} } ).then( res => {

  if(res.data.error) {

  } else { 
    doAnything( res.data )
  }

}).catch(function (error) {
   doAnythingError(error)
});

J'ai eu ce problème en utilisant fetch et axios a parfaitement fonctionné.

0
Evhz