Tornado服务器:启用CORS请求

ben*_*ams 10 tornado cors

我有一个简单的龙卷风服务器,它有类:

class BaseHandler(tornado.web.RequestHandler):
    def set_default_headers(self):
        print "setting headers!!!"
        self.set_header("Access-Control-Allow-Origin", "*")
Run Code Online (Sandbox Code Playgroud)

当发出常规(无CORS)请求时,服务器按预期应答,包括Access-Control-Allow-Origin标头.但是当我发出来自不同域(使用jQuery.post)的帖子请求时,响应为404并显示错误:"XMLHttpRequest无法加载http:// dev-machine:8090/handshake.No'Access -Control-Allow-Origin '标题出现在请求的资源上.因此,不允许来自' http:// localhost:8090 '的响应.响应的HTTP状态代码为404."

你能告诉我是否遗漏了什么吗?(另一个标题/其他配置/其他)

kwa*_*nek 32

您的代码缺少预检,OPTIONS请求.

https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS:

跨源资源共享标准的工作原理是添加新的HTTP标头,允许服务器描述允许使用Web浏览器读取该信息的起源集.此外,对于可能对用户数据造成副作用的HTTP请求方法(特别是对于GET以外的HTTP方法,或对某些MIME类型的POST使用),规范要求浏览器"预检"请求,请求支持的方法从具有HTTP OPTIONS请求方法的服务器,然后,在服务器"批准"时,使用实际的HTTP请求方法发送实际请求.服务器还可以通知客户端是否应随请求一起发送"凭据"(包括Cookie和HTTP身份验证数据).

要实现预检处理程序,只需添加具有相同标题且没有正文的选项处理程序.

class BaseHandler(tornado.web.RequestHandler):

    def set_default_headers(self):
        print "setting headers!!!"
        self.set_header("Access-Control-Allow-Origin", "*")
        self.set_header("Access-Control-Allow-Headers", "x-requested-with")
        self.set_header('Access-Control-Allow-Methods', 'POST, GET, OPTIONS')

    def post(self):
        self.write('some post')

    def get(self):
        self.write('some get')

    def options(self):
        # no body
        self.set_status(204)
        self.finish()
Run Code Online (Sandbox Code Playgroud)

编辑

我已将x-requested-with标题添加到允许列表中.这里是简单的jquery示例:

 $.ajax({
   url: "http://some_tornado/api",
   type: "POST",
   crossDomain: true,
   data: 'some_data',
   success: function (response) {
     alert(response);
   },
   error: function (xhr, status) {
     alert("error");
   }
 });
Run Code Online (Sandbox Code Playgroud)

还有一些关于cors的好文章 - http://dev.housetrip.com/2014/04/17/unleash-your-ajax-requests-with-cors/


小智 7

kwarunek的答案让我找到了解决PUT和DELETE请求问题的方法.唯一的问题是,该解决方案对于使用GET和POST的示例而言过于合适.在这种情况下的线

self.set_header("Access-Control-Allow-Origin", "*")
Run Code Online (Sandbox Code Playgroud)

实际上是足够的(如果浏览器之前没有阻止CORS).它与PUT和DELETE请求最相关.在网络级别上发生的事情可能比在GET/POST情况下稍微复杂一些.

"如果请求是"非简单"请求,浏览器首先发送无数据"预检"OPTIONS请求,以验证服务器是否接受请求.当使用除以外的HTTP动词时,请求是非简单的. GET或POST(例如PUT,DELETE)." 比照 非简单请求

class BaseHandler(tornado.web.RequestHandler):

    def set_default_headers(self):
        print("setting headers!!!")
        self.set_header("Access-Control-Allow-Origin", "*")
        self.set_header("Access-Control-Allow-Headers", "x-requested-with")
        self.set_header('Access-Control-Allow-Methods', ' PUT, DELETE, OPTIONS')

    def options(self):
        # no body
        self.set_status(204)
        self.finish()
Run Code Online (Sandbox Code Playgroud)

现在所有继承的处理程序BaseHandler都完全支持CORS:

class MyHandler(BaseHandler):

    def put(self):
        self.write('some post')

    def delete(self):
        self.write('some get')
Run Code Online (Sandbox Code Playgroud)