“WARNING:tornado.access:405”错误从“localhost”和“file://”来源停止 POST

Posted

技术标签:

【中文标题】“WARNING:tornado.access:405”错误从“localhost”和“file://”来源停止 POST【英文标题】:"WARNING:tornado.access:405" error stopping POST from both "localhost" and "file://" origins 【发布时间】:2017-12-07 14:10:46 【问题描述】:

这是一个与这个问题 (Tornado POST 405: Method Not Allowed) 非常相似的问题,但是该问题的死简单答案仍然不起作用。侧边栏还有很多很多类似的问题----->和Tornado无关,也没有给我提供解决方案。

现在我在 OSX 上使用 Firefox。

我的龙卷风代码如下:

import tornado.ioloop
import tornado.web

class MainHandler(tornado.web.RequestHandler):
    def post(self):
        self.write("Hello, world")
    get = post # <--------------

application = tornado.web.Application([
    (r"/", MainHandler),
])

if __name__ == "__main__":
    application.listen(8888)
    tornado.ioloop.IOLoop.instance().start()

如果我运行 GET,它可以正常工作,但如果我使用 POST,我会在客户端出现错误 HTTP/1.1 405 Method Not Allowed,而在服务器端出现错误 WARNING:tornado.access:405 OPTIONS。我尝试在 file://index.htmllocalhost:8000/index.html 设置中运行 js

我的测试 js 是这样的:

//this one returns the error
U.Ajax.post("http://localhost:8888/", "text", "data = fez hat")
.then(function(result) 
    console.log(result);
);

//this one works
U.Ajax.get("http://localhost:8888/", "text", "data = fez hat")
.then(function(result) 
    console.log(result);
);

如果有帮助的话,我的 ajax 代码如下所示:

//tested and functional ajax code, for ease of testing
U = ;
U.Ajax = ;
U.Ajax.send = function(getOrPost, url, dataType, data) 
    return new Promise( function(resolve, reject) 
        var request = new XMLHttpRequest();

        if(getOrPost == "GET") 
            request.responseType = dataType || "text";
            request.open("GET", url);   
        
        else //getOrPost == "POST"
            request.open("POST", url);  
            request.setRequestHeader('Content-type', dataType)
        


        request.onload = function() 
            if (request.status >= 200 && request.status < 400) 
                console.log("ajax", request.status+" "+url, request);

                resolve(request);               

             else 
                request.onerror();
            
        ;

        request.onerror = function() 
            var err = "include src '"+url+"' does not exist";
            console.log(err)
            reject(err)
        ;

        try 
            request.send(data); 
        
        catch(e) 
            var err = "NS_ERROR_DOM_BAD_URI: Access to restricted URI '"+url+"' denied";
            console.log(err)
            reject(err)
        


    );


U.Ajax.get = function(url, responseType) 
    return U.Ajax.send("GET", url, responseType);


U.Ajax.post = function(url, contentType, data) 
    return U.Ajax.send("POST", url, contentType, data);

编辑 :: 如果我将龙卷风代码更改为等同于 GET POST 和 OPTION,它可以工作,但不正确

class MainHandler(tornado.web.RequestHandler):
    def post(self):
        print(self.request)
    get = options = post # <--------------

我不再收到错误,但是当我打印 self.request 时,我的标题似乎以某种方式设置为“OPTIONS”

HTTPServerRequest(protocol='http', host='localhost:8888', method='OPTIONS', uri='/', version='HTTP/1.1', remote_ip='127.0.0.1', headers= 'Origin': 'null', 'Accept-Language': 'en-US,en;q=0.5', 'Accept-Encoding': 'gzip, deflate', 'Access-Control-Request-Headers': 'content -type', 'Host': 'localhost:8888', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8' , 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:55.0) Gecko/20100101 Firefox/55.0', 'Access-Control-Request-Method': 'POST', 'Connection': '保持活动')

【问题讨论】:

您使用的是什么 javascript 库? U.Ajax? 不,它几乎是从这个***.com/questions/8567114/…复制而来的 已找到半解,更新问题 “但是当我打印 self.request 时,我的标题似乎以某种方式设置为“OPTIONS”” – ...这可能只是意味着您正在查看 pre - 此类跨域请求所需的飞行请求。 您最好检查一下,是否从浏览器发送了OPTIONS请求(使用crhome的开发者工具或类似工具)。我认为这是javascript问题。 【参考方案1】:

我不再收到错误,但是当我打印 self.request 时,我的标题似乎以某种方式设置为“OPTIONS”

这将是 CORS 飞行前请求。

https://developer.mozilla.org/en-US/docs/Glossary/Preflight_request:

CORS 预检请求是检查 CORS 协议是否被理解的 CORS 请求。

这是一个使用两个 HTTP 请求标头的 OPTIONS 请求:Access-Control-Request-MethodAccess-Control-Request-Headers,以及 Origin 标头。

浏览器会在需要时自动发出预检请求;在正常情况下,前端开发人员不需要自己制作此类请求。

对于跨域 AJAX 请求,浏览器首先需要与远程服务器核对,是否要使用特定方法和/或特定请求标头接受请求。

这是通过 OPTIONS 请求实现的。当服务器在响应中表示客户端想要发出的实际请求是可接受的时,客户端就会发出该请求。

【讨论】:

【参考方案2】:

最近,我遇到了同样的问题。我使用以下代码解决了它:

import tornado.ioloop 
import tornado.web

class MainHandler(tornado.web.RequestHandler): 
    def set_default_headers(self):
        print('set headers!!')
        self.set_header('Access-Control-Allow-Origin', '*')
        self.set_header('Access-Control-Allow-Headers', '*')
        self.set_header('Access-Control-Max-Age', 1000)
        self.set_header('Content-type', 'application/json')
        self.set_header('Access-Control-Allow-Methods', 'POST, GET, OPTIONS')
        self.set_header('Access-Control-Allow-Headers',
                        'Content-Type, Access-Control-Allow-Origin, Access-Control-Allow-Headers, X-Requested-By, Access-Control-Allow-Methods')
    def OPTIONS(self):
        pass

application = tornado.web.Application([ (r"/", MainHandler), ])    
if name == "main":application.listen(8888)
    tornado.ioloop.IOLoop.instance().start()

【讨论】:

这对我有用,但我必须将选项设为小写。 对于其他读者:小心包含 Content-type': 'application-json' :这可能不适合您的应用 @RayB 有哪些选项?我不知道如何听从你的建议。 @javadba def options(self):

以上是关于“WARNING:tornado.access:405”错误从“localhost”和“file://”来源停止 POST的主要内容,如果未能解决你的问题,请参考以下文章