为什么通过AJAX发送POST被HTTP服务器解释为OPTIONS,而CURL发送实际上是PUT?

时间:2016-03-24 01:56:26

标签: javascript json ajax http

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

要测试RESTFul Web服务,我使用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测试来自AJAX的web服务时:

import matplotlib.pyplot as plt                                                 
import sympy                                                                    

x = sympy.symbols('x')                               
y = 1 + sympy.sin(sympy.sqrt(x**2 + 20))                                         
lat = sympy.latex(y)                                                            

#add text                                 
plt.text(0, 0.6, r"$%s$" % lat, fontsize = 50)                                  

#hide axes                                                                      
fig = plt.gca()                                                                 
fig.axes.get_xaxis().set_visible(False)                                         
fig.axes.get_yaxis().set_visible(False)                                         
plt.savefig('out.png', bbox_inches='tight', pad_inches=0)                                                        
plt.show()

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

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

这是带有Javascript请求的Firebug:

Firebug

1 个答案:

答案 0 :(得分:2)

出于安全原因,浏览器具有相同的原始策略。当您在浏览器中从与加载当前网页不同的原点请求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请求使用XML向服务器发送XML有效负载   application / xml或text / xml,然后请求被预检。它设定   请求中的自定义标头(例如,请求使用标头,例如   X-PINGOTHER)

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