web-dev-qa-db-fra.com

XMLHttpRequest change POST en OPTION

j'ai ce code:

net.requestXHR = function() {
    this.xhr = null;
    if(window.XMLHttpRequest === undefined) {
        window.XMLHttpRequest = function() {
            try {
                // Use the latest version of the activex object if available
                this.xhr = new ActiveXObject("Msxml2.XMLHTTP.6.0");
            }
            catch(e1) {
                try {
                    // Otherwise fall back on an older version
                    this.xhr = new ActiveXObject("Mxsml2.XMLHTTP.3.0");
                }
                catch(e2) {
                    //Otherwise, throw an error
                    this.xhr = new Error("Ajax not supported in your browser");
                }
            }
        };
    }
    else
        this.xhr = new XMLHttpRequest();
}
net.requestXHR.prototype.post = function(url, data) {
    if(this.xhr != null) {
        this.xhr.open("POST", url);
        this.xhr.setRequestHeader("Content-Type", "application/json");
        this.xhr.send(data);
    }
}

    var rs = new net.requestSpeech();
    console.log(JSON.stringify(interaction));
    rs.post("http://localhost:8111", JSON.stringify(interaction));

lorsque l'envoi s'exécute, j'ai ce journal:

OPTIONS http://localhost:8111/ [HTTP/1.1 405 Method Not Allowed 74ms]

Et dans localhost: 8111 j'ai un reslet serverResource qui accepte la publication, c'est un problème de même politique d'origine? j'ai modifié le restlet pour mettre l'en-tête allow-Origin et je le teste avec une autre requête GET http (en jquery) et fonctionne bien. J'ai le problème de la même résolution d'origine car j'utilise un navigateur html5 et mon serveur a mis les en-têtes dans la réponse, alors pourquoi l'envoi me montre cette erreur? pourquoi changer POST pour OPTION? Merci!

Duplication possible?: Je pense que non, mais c'est vrai, le problème est le même pour les deux questions, mais la mienne se réfère puisque la question qu'il y a un problème avec le navigateur, et l'autre, pointe d'abord vers jquery. Par expérience, le temps ne compte pas pour les doublons, les réponses sont différentes mais il est vrai que les deux questions se complètent.

48
Kalamarico

Oui, c'est un "problème avec la même politique d'origine". Vous effectuez votre demande soit vers un autre serveur, soit vers un autre port, ce qui signifie qu'il s'agit d'une demande HTTP intersite. Voici ce que la documentation a à dire sur ces requêtes:

De plus, pour les méthodes de requête HTTP qui peuvent provoquer des effets secondaires sur les données du serveur (en particulier, pour les méthodes HTTP autres que GET ou pour l'utilisation de POST avec certains types MIME), la spécification stipule que les navigateurs "contrôlent" la demande, en sollicitant les méthodes prises en charge auprès du serveur avec une méthode de demande HTTP OPTIONS, puis, sur "approbation" du serveur, en envoyant la demande réelle avec la méthode de demande HTTP réelle.

Il y a une description plus détaillée dans la section norme CORS ("Requête d'origine croisée avec contrôle en amont"). Votre serveur doit autoriser la demande OPTIONS et envoyer une réponse avec Access-Control-Allow-Origin, Access-Control-Allow-Headers et Access-Control-Allow-Methods en-têtes permettant la demande. Ensuite, le navigateur fera la demande POST réelle.

70
Wladimir Palant

J'avais ce problème exact à partir d'un code JavaScript qui a envoyé un contenu ajax.

Afin d'autoriser la demande d'origine croisée avec contrôle en amont, j'ai dû le faire dans le .ASPX qui recevait la pétition:

//Check the petition Method
if (Request.HttpMethod == "OPTIONS")
{
    //In case of an OPTIONS, we allow the access to the Origin of the petition
    string vlsOrigin = Request.Headers["Origin"];
    Response.AddHeader("Access-Control-Allow-Origin", vlsOrigin);
    Response.AddHeader("Access-Control-Allow-Methods", "POST");
    Response.AddHeader("Access-Control-Allow-Headers", "accept, content-type");
    Response.AddHeader("Access-Control-Max-Age", "1728000");
}

Vous devez être prudent et vérifier quels en-têtes sont demandés par votre pétition. J'ai vérifié ceux qui utilisaient Fiddler.

J'espère que cela servira quelqu'un à l'avenir.

9
Javier Arteagoitia

Comme d'autres l'ont souligné, c'est une chose CORS.

Voici comment le gérer dans NGINX (basé sur cette source ):

location / {
    if ($request_method = OPTIONS ) {
        add_header Access-Control-Allow-Origin "http://example.com";
        add_header Access-Control-Allow-Methods "GET, OPTIONS";
        add_header Access-Control-Allow-Headers "Authorization";
        add_header Access-Control-Allow-Credentials "true";
        add_header Content-Length 0;
        add_header Content-Type text/plain;
        return 200;
    }
}

Si vous souhaitez autoriser les demandes CORS de toute origine, remplacez,

add_header Access-Control-Allow-Origin "http://example.com";

avec

add_header Access-Control-Allow-Origin "*";

Si vous n'utilisez pas d'autorisation, vous n'aurez pas besoin de ce bit:

add_header Access-Control-Allow-Headers "Authorization";
add_header Access-Control-Allow-Credentials "true";

Pour l'API que je développe, j'avais besoin de mettre en liste blanche 3 méthodes de demande: GET, POST et OPTIONS, et un X-App-Id header, alors voici ce que j'ai fini par faire:

if ($request_method = OPTIONS ) {
    add_header Access-Control-Allow-Origin "*";
    add_header Access-Control-Allow-Methods "GET, POST, OPTIONS";
    add_header Access-Control-Allow-Headers "X-App-Id";
    add_header Content-Length 0;
    add_header Content-Type text/plain;
    return 200;
}
2
Nino Škopac