Making a pretty straightforward Tornado app, but something that seems impossible is happening based on my understanding of Tornado. In short I've got the following RequestHandler
:
class CreateUserHandler(tornado.web.RequestHandler):
def post(self):
print self.request.body
print self.get_body_argument("email")
# Do other things
And the following is what is printed:
{"email":"slater@indico.io","password":"password"}
WARNING:tornado.general:400 POST /user/create/ (::1): Missing argument email
So email clearly exists in the body, and yet when trying to access it a 400 is raised. I could manually parse the request body, but Tornado's error handling is nice enough that I'd like to avoid rewriting it if possible.
So, my basic question is how is this possible? It's printing the correct request body, and then is somehow unable to access the dictionary it just printed.
get_body_argument
is intended for form-encoded data, as you have discovered. Tornado has little support built-in for JSON data in request bodies. You can simply:
import json
class CreateUserHandler(tornado.web.RequestHandler):
def post(self):
data = json.loads(self.request.body)
print data.get("email")
Here's a little helper method I've been adding to my handlers in order to retrieve all of the body arguments as a dict:
from tornado.web import RequestHandler
from tornado.escape import json_decode
class CustomHandler(RequestHandler):
def get_all_body_arguments(self):
"""
Helper method retrieving values for all body arguments.
Returns:
Dict of all the body arguments.
"""
if self.request.headers['Content-Type'] == 'application/json':
return json_decode(self.request.body)
return {arg: self.get_body_argument(arg) for arg in self.request.arguments}
Not sure why this is the case, but I found a resolution. It required both url-encoding the body (this seems very strange to me as it's a request payload), and changing the Content-Type
header to application/x-www-form-urlencoded
This is the new output of the script above:
email=slater%40indico.io&password=password
slater@indico.io