为啥我的跨域 POST 请求预检了 OPTIONS 请求?

Posted

技术标签:

【中文标题】为啥我的跨域 POST 请求预检了 OPTIONS 请求?【英文标题】:Why is my cross-domain POST request being preflighted with an OPTIONS request?为什么我的跨域 POST 请求预检了 OPTIONS 请求? 【发布时间】:2011-03-30 05:05:26 【问题描述】:

根据 Mozilla 开发者中心HTTP access control 文章,跨站点 POST 请求可以是“简单的”——即不需要预检——如果请求的 Content-Type 是 application/x-www-form-urlencoded

我在 Firefox 中没有遇到这种行为,我完全不明白为什么会这样。这是我的设置代码:

function makeXDomainRequest(url, method, data) 
    var req =
        typeof XDomainRequest !== "undefined" ?
        new XDomainRequest() : new XMLHttpRequest();

    req.open(method || "GET", url, true);

    if (typeof req.onload !== "undefined") 
        req.onload = onResponseLoad;
        req.onerror = onRequestError;
     else 
        req.onreadystatechange = onRequestStateChange;
    

    if (data && typeof req.setRequestHeader === "function") 
        req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
     else 
        // no way to set Content-Type req header in IE's XDomainRequest:
        // http://blogs.msdn.com/b/ieinternals/archive/2010/05/13/xdomainrequest-restrictions-limitations-and-workarounds.aspx
    

    req.send(data || null);


function onResponseLoad() 
    alert("Response!\n" + this.responseText);


function onRequestError(args) 
    alert("Error!");


function onRequestStateChange() 
    if (this.readyState === 4) 
        if (this.status === 200) 
            onResponseLoad.apply(this);
         else 
            onRequestError.apply(this);
        
    

这是我正在 ping 的服务器:

// thanks to http://saltybeagle.com/cors/ for having this demo endpoint:
var URL = "http://ucommbieber.unl.edu/CORS/cors.php";

现在,如果我执行一个简单的 POST 请求——在上面的代码中以application/x-www-form-urlencoded 发送数据——该请求在 Firefox 中使用 OPTIONS 请求进行预检。它没有在 Chrome 中预检。在运行之前打开 Fiddler 亲自查看:

makeXDomainRequest(URL, "POST", "name=foobar");
// alerts "Response! Hello CORS [...] You sent a POST request. Your name is foobar"

这是 Fiddler 中的预检 OPTIONS 请求(请注意 Access-Control-Request-Method: POST 标头,即使我指定了所谓的安全 Content-Type 并且没有自定义标头):

OPTIONS http://ucommbieber.unl.edu/CORS/cors.php HTTP/1.1
Host: ucommbieber.unl.edu
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.2.8) Gecko/20100722 Firefox/3.6.8
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 115
Connection: keep-alive
Origin: http://localhost
Access-Control-Request-Method: POST

发生了什么事?这是 Firefox 中的错误,还是我做错了什么?谢谢!

【问题讨论】:

【参考方案1】:

这确实是一个 Firefox 错误。它最终得到了 FF4b6 的修复:https://bugzilla.mozilla.org/show_bug.cgi?id=588920

【讨论】:

以上是关于为啥我的跨域 POST 请求预检了 OPTIONS 请求?的主要内容,如果未能解决你的问题,请参考以下文章

带有预检的 Node.JS 中的跨域 POST 请求?

http跨域预检问题

preflight request预检请求

发送带有自定义 HTTP 标头的跨域请求时禁用预检 OPTION 请求

为啥会有OPTIONS请求

一句话概括options预检请求+后端跨域代码解释——打破前后端联调的理解障碍