Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Tornado server: enable CORS requests

Tags:

cors

tornado

I have a simple tornado server which has the class:

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

When a regular (no CORS) request is made, the server answers as expected, including the Access-Control-Allow-Origin header. But when I make a post request coming from different domain (using jQuery.post), the response is 404 and an error is displayed: "XMLHttpRequest cannot load http://dev-machine:8090/handshake. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8090' is therefore not allowed access. The response had HTTP status code 404."

Can you tell if I miss something? (another header/other configuration/anything else)

like image 716
benams Avatar asked Feb 07 '16 14:02

benams


People also ask

How do I enable allow CORS?

Simply add a header to your HttpServletResponse by calling addHeader : response. addHeader("Access-Control-Allow-Origin", "*");

How do I know if my server is CORS enabled?

You can either send the CORS request to a remote server (to test if CORS is supported), or send the CORS request to a test server (to explore certain features of CORS). Send feedback or browse the source here: https://github.com/monsur/test-cors.org.


1 Answers

Your code is missing preflight, the OPTIONS request.

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

The Cross-Origin Resource Sharing standard works by adding new HTTP headers that allow servers to describe the set of origins that are permitted to read that information using a web browser. Additionally, for HTTP request methods that can cause side-effects on user data (in particular, for HTTP methods other than GET, or for POST usage with certain MIME types), the specification mandates that browsers "preflight" the request, soliciting supported methods from the server with an HTTP OPTIONS request method, and then, upon "approval" from the server, sending the actual request with the actual HTTP request method. Servers can also notify clients whether "credentials" (including Cookies and HTTP Authentication data) should be sent with requests.

To implement preflight handler simply add options handler with the same headers and no body.

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, *args):
        # no body
        # `*args` is for route with `path arguments` supports
        self.set_status(204)
        self.finish()

edit

I've added x-requested-with header to allowed list. And here is simple jquery sample:

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

And some really good article about cors - http://dev.housetrip.com/2014/04/17/unleash-your-ajax-requests-with-cors/

like image 191
kwarunek Avatar answered Sep 19 '22 13:09

kwarunek