XMLHttpRequest changes POST to OPTION

JavascriptXmlhttprequest

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionKalamaricoView Question on Stackoverflow
Solution 1 - JavascriptWladimir PalantView Answer on Stackoverflow
Solution 2 - JavascriptJavier ArteagoitiaView Answer on Stackoverflow
Solution 3 - JavascriptShailesh PratapwarView Answer on Stackoverflow
Solution 4 - JavascriptThe OninView Answer on Stackoverflow