XMLHttpRequest changes POST to OPTION
JavascriptXmlhttprequestJavascript Problem Overview
i have this 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));
when the send execute, i have this log:
OPTIONS http://localhost:8111/ [HTTP/1.1 405 Method Not Allowed 74ms]
And in localhost:8111 i have a reslet serverResource that accept post, it is problem of same origin policy? i have modify the restlet to put the allow-origin header and i test it with another GET http request (in jquery) and work ok. I have the problem of same origin resolve because i use an html5 browser and my server put the headers in the response, so why the send shows me this error? why change POST for OPTION? Thanks!
> Possible duplicate?: I think no, but it's true, the problem is the > same for both questions, but mine are refers since the question that > there is an issue with the browser, and the other, first points to > jquery. By experience the time does not count for duplicate, the > answers are different but it's true that both questions complement > each other.
Javascript Solutions
Solution 1 - Javascript
Yes, this is a "problem with same-origin policy". You are making your request either to a different server or to a different port, meaning that it is a cross-site HTTP request. Here is what the documentation has to say about such requests:
> Additionally, for HTTP request methods that can cause side-effects on
> server's data (in particular, for HTTP methods other than GET
, or for
> POST
usage with certain MIME types), the specification mandates that
> browsers "preflight" the request, soliciting supported methods from
> the server with an HTTP OPTIONS
request method, and then, upon
> "approval" from the server, sending the actual request with the actual
> HTTP request method.
There is a more detailed description in the CORS standard ("Cross-Origin Request with Preflight" section). Your server needs to allow the OPTIONS
request and send a response with Access-Control-Allow-Origin
, Access-Control-Allow-Headers
and Access-Control-Allow-Methods
headers allowing the request. Then the browser will make the actual POST
request.
Solution 2 - Javascript
I was having this exact problem from a JavaScript code that sent an ajax content.
In order to allow the Cross-Origin Request with Preflight I had to do this in the .ASPX that was receiving the petition:
//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");
}
You have to be careful and check what headers are being asked by your petition. I checked those using Fiddler.
Hope this serves someone in the future.
Solution 3 - Javascript
Answer:
Your browser is initiating a PreFlight OPTIONS request.
Why: Because your request is not a simple request.
Why it is not a simple request: Because of "Content-Type" = "application/json".
Solution: Try to use either of below content types :
- application/x-www-form-urlencoded
- multipart/form-data
- text/plain
Solution 4 - Javascript
As others have pointed out, this is a CORS thing.
This is how to handle it in NGINX (based on 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;
}
}
If you want to allow CORS requests from any origin, replace,
add_header Access-Control-Allow-Origin "http://example.com";
with
add_header Access-Control-Allow-Origin "*";
If you don't use authorization, you won't need this bit:
add_header Access-Control-Allow-Headers "Authorization";
add_header Access-Control-Allow-Credentials "true";
For the API I'm developing I needed to whitelist 3 request methods: GET, POST and OPTIONS, and an X-App-Id
header, so this us what I ended up doing:
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;
}