【问题标题】:XMLHttpRequest changes POST to OPTIONXMLHttpRequest 将 POST 更改为 OPTION
【发布时间】:2011-12-30 12:42:31
【问题描述】:

我有这个代码:

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

当发送执行时,我有这个日志:

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

在 localhost:8111 我有一个接受 post 的 reslet serverResource,这是同源策略的问题吗?我已经修改了restlet以放置allow-origin标头,并使用另一个GET http请求(在jquery中)对其进行测试并且工作正常。我解决了同源问题,因为我使用的是 html5 浏览器,而我的服务器将标头放入响应中,那么为什么发送显示此错误?为什么将 POST 更改为 OPTION? 谢谢!

可能重复?:我认为没有,但确实如此,问题在于 两个问题都一样,但我的问题是 浏览器有问题,另一个首先指向 jQuery。根据经验,时间不算重复, 答案是不同的,但确实这两个问题都是互补的 彼此。

【问题讨论】:

标签: javascript xmlhttprequest


【解决方案1】:

是的,这是“同源策略问题”。您正在向不同的服务器或不同的端口发出请求,这意味着它是一个跨站点 HTTP 请求。以下是the documentation 对此类请求的看法:

另外,对于可能导致副作用的 HTTP 请求方法 服务器的数据(特别是对于GET 以外的 HTTP 方法,或者对于 POST 与某些 MIME 类型一起使用),规范要求 浏览器“预检”请求,从 使用 HTTP OPTIONS 请求方法的服务器,然后,在 来自服务器的“批准”,发送带有实际请求的实际请求 HTTP 请求方法。

CORS standard(“带预检的跨域请求”部分)中有更详细的描述。您的服务器需要允许OPTIONS 请求并发送带有Access-Control-Allow-OriginAccess-Control-Allow-HeadersAccess-Control-Allow-Methods 标头的响应以允许该请求。然后浏览器会发出实际的POST 请求。

【讨论】:

  • 无法修改服务器行为的情况下怎么办?我无法访问它的源代码
  • @gbaor:您可以使用没有同源限制的JSONP,或者(如果服务器也不支持)您可以在自己的服务器上运行服务器端脚本,该脚本将从其他服务器请求数据并将其返回 - 然后您的 JavaScript 代码可以从您的服务器获取此数据,该数据是同源的。
【解决方案2】:

我在发送 ajax 内容的 JavaScript 代码中遇到了这个确切的问题。

为了通过 Preflight 允许跨域请求,我必须在接收请求的 .ASPX 中执行此操作:

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

您必须小心并检查您的请愿书要求的标题。我检查了那些使用 Fiddler 的。

希望这对将来的某人有所帮助。

【讨论】:

    【解决方案3】:

    正如其他人指出的那样,这是 CORS 的事情。

    这是在NGINX中的处理方式(基于 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;
        }
    }
    

    如果您想允许来自任何来源的 CORS 请求,请替换,

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

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

    如果你不使用授权,你就不需要这个位:

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

    对于我正在开发的 API,我需要将 3 个请求方法列入白名单:GET、POST 和 OPTIONS,以及一个 X-App-Id 标头,所以这就是我最终要做的:

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

    【讨论】:

      【解决方案4】:

      答案:

      您的浏览器正在发起PreFlight OPTIONS 请求。

      原因: 因为您的请求不是simple request

      为什么这不是一个简单的请求: 因为“Content-Type”=“application/json”。

      解决方案: 尝试使用以下任一内容类型:

      • application/x-www-form-urlencoded
      • 多部分/表单数据
      • 文本/纯文本

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-10-27
        • 1970-01-01
        • 1970-01-01
        • 2017-11-09
        • 2020-02-03
        • 1970-01-01
        • 2017-09-27
        • 2014-05-14
        相关资源
        最近更新 更多