2011-11-16 15 views
34

ho questo codice:XMLHttpRequest cambia POST per OPZIONE

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)); 

quando l'invio di esecuzione, ho questo registro:

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

E in localhost: 8111 ho un serverResource reslet che accetta posta , è un problema della stessa politica di origine? Ho modificato il restlet per inserire l'intestazione allow-origin e lo collaudo con un'altra richiesta http GET (in jQuery) e funziona bene. Ho il problema della risoluzione dell'origine perché utilizzo un browser html5 e il mio server inserisce le intestazioni nella risposta, quindi perché l'invio mi mostra questo errore? perché cambiare POST per OPTION? Grazie!

duplicato possibile ?: Credo che nessuno, ma è vero, il problema è la stesso per entrambe le domande, ma la mia sono si riferisce in quanto la domanda che c'è un problema con il browser, e l'altro, prima punta a jquery. Per esperienza il tempo non conta per i duplicati, le risposte sono diverse, ma è vero che entrambe le domande completano lo a vicenda.

+0

Possibile duplicato di [Perché sto ricevendo una richiesta OPTIONS invece di una richiesta GET?] (Https://stackoverflow.com/questions/1256593/why-am-i-getting-an-options-request-instead-of-a -get-request) – Carvallegro

risposta

56

Sì, questo è un "problema con la politica della stessa origine". Stai facendo la tua richiesta su un server diverso o su una porta diversa, il che significa che si tratta di una richiesta HTTP cross-site. Ecco cosa the documentation ha da dire su tali richieste:

Inoltre, per i metodi di richiesta HTTP che possono causare effetti collaterali sui dati del server (in particolare, per i metodi HTTP diversi GET, o per POST utilizzo con alcuni tipi MIME), la specifica specifica che i browser "preflight" la richiesta, sollecitando i metodi supportati da il server con un metodo di richiesta HTTP OPTIONS e quindi, dopo l'approvazione " " dal server, inviando la richiesta effettiva con l'effettiva Metodo di richiesta HTTP.

C'è una descrizione più dettagliata nella sezione CORS standard ("Richiesta di origine incrociata con preflight"). Il server deve consentire la richiesta OPTIONS e inviare una risposta con Access-Control-Allow-Origin, Access-Control-Allow-Headers e Access-Control-Allow-Methods intestazioni che consentono la richiesta. Quindi il browser effettuerà la richiesta effettiva POST.

+1

Cosa posso fare nel caso in cui non riesca a modificare il comportamento del server? Non riesco ad accedere al suo codice sorgente – gbaor

+1

@gbaor: Puoi usare [JSONP] (http://en.wikipedia.org/wiki/JSONP) che non ha restrizioni della stessa origine o (se il server non supporta quello) è possibile eseguire uno script sul lato server sul proprio server che richiederà i dati dall'altro server e restituirli, quindi il codice JavaScript può ottenere questi dati dal server che ha la stessa origine. –

9

Avevo questo problema esatto da un codice JavaScript che inviava un contenuto Ajax.

Al fine di consentire la richiesta di Cross-Origin con Preflight ho dovuto fare questo nel .aspx che stava ricevendo la petizione:

//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"); 
} 

Bisogna stare attenti e controllare quali sono le intestazioni essendo chiesto dalla tua petizione. Ho controllato quelli usando Fiddler.

Spero che questo serva qualcuno in futuro.

1

Come altri hanno sottolineato, questa è una cosa CORS.

Questo è il modo di gestire la cosa in Nginx (sulla base di this 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; 
    } 
} 

Se si desidera consentire le richieste CORS da qualsiasi origine, sostituire,

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

con

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

Se non si utilizza l'autorizzazione, non sarà necessario questo bit:

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

Per l'API sto sviluppando avevo bisogno di whitelist 3 metodi di richiesta: GET, POST e opzioni, e un X-App-Id intestazione, quindi questo noi quello che ho finito per fare:

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; 
}