为什么通过AJAX发送POST由HTTP Server解释为OPTIONS,而通过CURL发送实际上是PUT? [英] Why sending a POST by AJAX is interpreted by the HTTP Server as OPTIONS and sending by CURL is effectively a PUT?

查看:214
本文介绍了为什么通过AJAX发送POST由HTTP Server解释为OPTIONS,而通过CURL发送实际上是PUT?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm testing a HTTP Server that I have developed myself with C++ and Boost libraries. More specifically, I'm testing an endpoint where a JSON is received by PUT.

要测试RESTFul Web服务,我将Curl与以下命令配合使用:

To test the RESTFul webservice I use Curl with the following command:

卷曲-H内容类型:应用程序/json" -H内容长度:34" -H连接:关闭" -X PUT --data"@response_json" 其中response_json是带有要发送的json的文件.这可以正常工作,服务器将请求作为PUT接收并执行应做的事情.

where response_json is a file with the json to be sent. This works fine, the server receives the request as a PUT and do what is supposed to do.

但是,当我以此测试来自AJAX的Web服务时:

However, when I test the webservice from AJAX with this:

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

the server receives it as OPTIONS and does not work. Moreover, in Firebug console I can see: "NetworkError: 404 Not Found - http://localhost:8080/answer".

我已经尝试使用Firefox和Chrome.我的JavaScript代码有什么问题?

I have tried with Firefox and Chrome. What is wrong in my javascript code?

这是带有Javascript请求的Firebug:

This is the Firebug with the request from Javascript:

推荐答案

出于安全原因,浏览器具有相同的原始策略.当您在浏览器中从不同于加载当前网页的来源请求浏览器中的Ajax PUT时,该请求将遵循相同的来源策略.目标站点可以选择支持CORS(跨源资源共享),这是浏览器实现的特定方案,可让其询问目标站点是否有特定的跨源请求.

The browser has a same origin policy for security reasons. When you request a Ajax PUT in the browser from a different origin than the current web page was loaded from, then the request is subject to that same origin policy. The destination site can choose to support CORS (cross origin resource sharing) which is a specific scheme that the browser implements that lets it ask the target site if a specific cross origin request is OK or not.

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

Using the OPTIONS request before the PUT request is one such part of the CORS scheme. If the browser detects certain conditions on the original cross origin request, then it will first issue an OPTIONS request and, if it gets the right response from that, then it will issue the target request (a PUT in your case). Things that can trigger the browser to use the OPTIONS request are things like custom headers, certain types of authorization required, certain content types, certain types of requests, etc...

CURL没有实施相同的原始安全性(即为自己的网页安全性模型发明的浏览器),因此它只是直接发送PUT请求,而无需先从OPTIONS请求中获得正确答案

CURL, on the other hand, enforces no such same origin security (that is someting a browser invented for its own web page security model) so it just sends the PUT request right through without requiring the correct answer from the OPTIONS request first.

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

FYI, if the Javascript in the browser that is making the Ajax request is requesting from the same origin as the loaded web page that contains the Javascript, then it should not trigger the OPTIONS request because it would be a same origin request rather than a cross origin request. If you have a local server, make sure that the web page is being loaded from the local server (same hostname and port number) too, not from the file system and not one using an IP address and the other using localhost or something like that. As far as the browser is concerned, the hostname has to physically be the same, not just the same IP address.

这是来自 MDN 的信息,其中请求已被预处理" "和"OPTIONS"请求:

Here's info from MDN on what requests are "preflighted" with the OPTIONS request:

已请求的请求

Preflighted requests

与简单请求(如上所述)不同,预检"请求优先 通过OPTIONS方法将HTTP请求发送到资源上的 其他域,以确定实际请求是否安全 发送.跨站点请求会像这样被预检,因为它们可能 对用户数据有影响.特别是,一个请求是 预检是否满足以下条件:

Unlike simple requests (discussed above), "preflighted" requests first send an HTTP request by the OPTIONS method to the resource on the other domain, in order to determine whether the actual request is safe to send. Cross-site requests are preflighted like this since they may have implications to user data. In particular, a request is preflighted if:

它使用GET,HEAD或POST以外的方法.另外,如果使用POST 发送具有Content-Type以外的Content-Type的请求数据 application/x-www-form-urlencoded,multipart/form-data或text/plain, 例如如果POST请求使用以下命令向服务器发送XML负载 application/xml或text/xml,则该请求被预检.它设置 请求中的自定义标头(例如,请求使用标头,例如 X-PINGOTHER)

It uses methods other than GET, HEAD or POST. Also, if POST is used to send request data with a Content-Type other than application/x-www-form-urlencoded, multipart/form-data, or text/plain, e.g. if the POST request sends an XML payload to the server using application/xml or text/xml, then the request is preflighted. It sets custom headers in the request (e.g. the request uses a header such as X-PINGOTHER)

仅供参考,这是对CORS各个方面的很好的解释.由于您的请求是PUT,因此将在该文章的不太简单的请求"部分中.

FYI, here's a pretty good explanation of the various aspects of CORS. Because your request is a PUT, it will be in the "not-so-simple request" part of that article.

这篇关于为什么通过AJAX发送POST由HTTP Server解释为OPTIONS,而通过CURL发送实际上是PUT?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆