【问题标题】:Why sending a POST by AJAX is interpreted by the HTTP Server as OPTIONS and sending by CURL is effectively a PUT?为什么通过 AJAX 发送 POST 被 HTTP 服务器解释为 OPTIONS 而通过 CURL 发送实际上是 PUT?
【发布时间】:2016-07-11 13:22:58
【问题描述】:

我正在测试自己使用 C++ 和 Boost 库开发的 HTTP 服务器。更具体地说,我正在测试 PUT 接收 JSON 的端点。

为了测试 RESTFul 网络服务,我使用 Curl 和以下命令:

curl -H "Content-Type: application/json" -H "Content-Length: 34" -H "Connection: close" -X PUT --data "@response_json" http://localhost:8080/answer

其中 response_json 是一个包含要发送的 json 的文件。这工作正常,服务器将请求作为 PUT 接收并执行应该执行的操作。

但是,当我使用 AJAX 测试 Web 服务时:

function sendPut2() {
    var http = new XMLHttpRequest();
    var url = 'http://localhost:8080/answer';
    var data = JSON.stringify({"question": "a", "answer": "b"});
    http.open("PUT", url, true);
    http.setRequestHeader("Content-type", "application/json");
    http.setRequestHeader("Content-Length", data.length);
    http.setRequestHeader("Connection", "close");
    http.onreadystatechange = function() { 
        if(http.readyState == 4 && http.status == 200) {
            alert(http.responseText);
        }
    }
    http.send(data);
}

服务器将其作为 OPTIONS 接收并且不起作用。此外,在 Firebug 控制台中,我可以看到:“NetworkError: 404 Not Found - http://localhost:8080/answer”。

我尝试过使用 Firefox 和 Chrome。我的 javascript 代码有什么问题?

这是来自 Javascript 的请求的 Firebug:

【问题讨论】:

  • 确保你打的是同一个原点,如果不是,有两个选项。 1. 服务器必须使用 access-control-allow-origins 标头进行响应。 2.临时安装chrome cors插件
  • Chrome CORS 插件并没有真正解决 OPTIONS 的问题。在某些情况下,最好使用 chrome 的 --disable-web-security 命令行选项进行测试。

标签: javascript json ajax http


【解决方案1】:

出于安全原因,浏览器具有同源策略。当您在浏览器中从不同于加载当前网页的来源请求 Ajax PUT 时,该请求将受相同来源策略的约束。目标站点可以选择支持 CORS(跨源资源共享),这是浏览器实现的一种特定方案,允许它询问目标站点特定的跨源请求是否正常。

在 PUT 请求之前使用 OPTIONS 请求是 CORS 方案的这样一部分。如果浏览器在原始跨源请求中检测到某些条件,那么它将首先发出一个 OPTIONS 请求,如果它从中获得正确的响应,那么它将发出目标请求(在您的情况下为 PUT)。可以触发浏览器使用 OPTIONS 请求的事情是自定义标头、所需的某些类型的授权、某些内容类型、某些类型的请求等...

另一方面,CURL 不强制执行同源安全性(即浏览器为其自己的网页安全模型发明的某些东西),因此它只是直接发送 PUT 请求,而无需首先从 OPTIONS 请求中获得正确答案.


仅供参考,如果发出 Ajax 请求的浏览器中的 Javascript 请求来自与包含 Javascript 的已加载网页相同的来源,那么它不应触发 OPTIONS 请求,因为它将是同源请求而不是而不是跨源请求。如果您有本地服务器,请确保网页也是从本地服务器(相同的主机名和端口号)加载的,而不是从文件系统加载,也不是一个使用 IP 地址,另一个使用 localhost 或类似的东西.就浏览器而言,主机名在物理上必须相同,而不仅仅是相同的 IP 地址。


以下是来自 MDN 的关于 OPTIONS 请求“预检”了哪些请求的信息:

预检请求

与简单的请求(上面讨论过)不同,“预检”请求首先 通过 OPTIONS 方法向资源上的资源发送 HTTP 请求 其他域,以判断实际请求是否安全 发送。跨站点请求是这样预检的,因为它们可能 对用户数据有影响。特别是,请求是 预检如果:

它使用 GET、HEAD 或 POST 以外的方法。此外,如果使用 POST 发送 Content-Type 以外的请求数据 application/x-www-form-urlencoded、multipart/form-data 或 text/plain, 例如如果 POST 请求使用 application/xml 或 text/xml,然后预检请求。它设置 请求中的自定义标头(例如,请求使用标头,例如 X-PINGOTHER)

仅供参考,这是 CORS 各个方面的pretty good explanation。因为您的请求是 PUT,所以它将在该文章的“不那么简单的请求”部分中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-07-27
    • 1970-01-01
    • 2013-02-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-19
    相关资源
    最近更新 更多