Tornado Server: Allow CORS Requests

I have a simple tornado server that has a class:

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

When a regular request (CORS) is executed, the server responds as expected, including the Access-Control-Allow-Origin header. But when I make a mail request from different domains (using jQuery.post ), the answer is 404 and an error is displayed: "XMLHttpRequest cannot load http: // dev-machine: 8090 / handshake There is no header in the requested resource" Access-Control- Allow-Origin ". Therefore, Origin ' http: // localhost: 8090 ' is not allowed access. The response had an HTTP status code of 404."

Can you say that I missed something? (different header / different configuration / something else)

+5
source share
3 answers

There is no preflight in the code, an OPTIONS request.

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

The Cross-Origin resource sharing standard works by adding a new HTTP protocol that allows servers to describe a set of sources that are allowed to read this information using a web browser. Additionally, for HTTP request methods that can cause side effects for user data (in particular, for HTTP methods other than GET, or for using POST with certain MIME types), the specification requires browsers to "precede" the request. requesting supported methods from the server using the HTTP OPTIONS request method, and then after approval, the server sending the actual request with the actual HTTP request method. Servers can also notify clients about whether "credentials" (including cookies and HTTP authentication) should be sent with requests.

To implement a preview handler, simply add a parameter handler with the same headers and without a 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): # no body self.set_status(204) self.finish() 

change

I added the x-requested-with header to the allowed list. And here is a simple jquery example:

  $.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 articles about bark - http://dev.housetrip.com/2014/04/17/unleash-your-ajax-requests-with-cors/

+23
source

Kwarunek's answer led me to solve my problem with a PUT and DELETE request. The only solution is overly suitable for the example with GET and POST. In this case, the line

 self.set_header("Access-Control-Allow-Origin", "*") 

actually enough (unless the browser blocks CORS in front of everyone). This is most relevant for PUT and DELETE queries. What happens here at the network level can be a bit more complicated than with GET / POST.

"If the request is a" difficult "request, the browser first sends the OPTIONS request without a preview to make sure the server accepts the request. The request is not simple when using an HTTP verb other than GET or POST (for example, PUT, DELETE)." cf. difficult requests

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

Now all the handlers that inherit from BaseHandler are fully compatible with CORS:

 class MyHandler(BaseHandler): def put(self): self.write('some post') def delete(self): self.write('some get') 
+5
source

Even with previous answers, I got the following CORS error:

Cross-request request is blocked: a policy of the same origin prohibits reading the remote resource at http://127.0.0.1:9999/home?message=Input%20to%20API .. (Reason: token 'access-control-allow-origin is missing in the header CORS "Access-Control-Allow-Headers from the CORS Preview Channel).

and the decision should also include the headings:

 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', 'GET, PUT, DELETE, OPTIONS') # HEADERS! self.set_header("Access-Control-Allow-Headers", "access-control-allow-origin,authorization,content-type") def options(self): # no body self.set_status(204) self.finish() 
0
source

Source: https://habr.com/ru/post/1242483/


All Articles