我正在测试我自己使用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:
答案 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,所以它将在该文章的“不那么简单的请求”部分。