“WARNING:tornado.access:405” error stopping POST from both “localhost” and “file://” origins

[亡魂溺海] 提交于 2019-12-13 00:48:17

问题


This is a very similar problem to this question (Tornado POST 405: Method Not Allowed), but the dead simple answer for that question is still not working. There are also many, many more similar questions in the side bar -----> which are not related to Tornado, and did not provide me with a solution.

Right now I am using Firefox on OSX.

My tornado code is as follows:

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()

If I run GET, it works fine, but if I use POST, I get the error on client side HTTP/1.1 405 Method Not Allowed and the error on server side WARNING:tornado.access:405 OPTIONS. I have tried running the js in both a file://index.html and localhost:8000/index.html setting

My test js looks like this:

//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);
});

My ajax code looks like this, if that's any help:

//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);
}

EDIT :: If I change the tornado code to equate GET POST and OPTION, it works, but incorrectly

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

I no longer get an error, but when I print self.request it appears that my headers are set to "OPTIONS" somehow

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': 'keep-alive'})


回答1:


I no longer get an error, but when I print self.request it appears that my headers are set to "OPTIONS" somehow

That would be the CORS pre-flight request.

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

A CORS preflight request is a CORS request that checks to see if the CORS protocol is understood.

It is an OPTIONS request using two HTTP request headers: Access-Control-Request-Method and Access-Control-Request-Headers, and the Origin header.

A preflight request is automatically issued by a browser when needed; in normal cases, front-end developers don't need to craft such requests themselves.

For cross-domain AJAX requests, the browser first needs to check with the remote server, whether it wants to accept a request using a specific method and/or specific request headers.

That happens via an OPTIONS request. And when the server signals in the response that the actual request the client wants to make is acceptable, the client then makes that request.




回答2:


Recently, I have met the same problem. I solved it using the following code:

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()


来源:https://stackoverflow.com/questions/44900282/warningtornado-access405-error-stopping-post-from-both-localhost-and-file

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!