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/