56

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.

Kalamarico
  • 5,466
  • 22
  • 53
  • 70
  • Possible duplicate of [Why am I getting an OPTIONS request instead of a GET request?](https://stackoverflow.com/questions/1256593/why-am-i-getting-an-options-request-instead-of-a-get-request) – Carvallegro Sep 20 '17 at 22:36

4 Answers4

82

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. 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.

Boris Verkhovskiy
  • 14,854
  • 11
  • 100
  • 103
Wladimir Palant
  • 56,865
  • 12
  • 98
  • 126
  • 3
    What can I do in the case when I can not modify the server's behaviour? I can not access it's source code – gbaor Jul 22 '14 at 11:38
  • 2
    @gbaor: You can use [JSONP](http://en.wikipedia.org/wiki/JSONP) which has no same-origin restrictions or (if the server doesn't support that either) you can run a server-side script on your own server that will request the data from the other server and return it - then your JavaScript code can get this data from your server which is same origin. – Wladimir Palant Jul 22 '14 at 11:54
10

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.

6

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
Shailesh Pratapwar
  • 4,054
  • 3
  • 35
  • 46
3

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;
}
The Onin
  • 5,068
  • 2
  • 38
  • 55