user1363445
user1363445

Reputation: 323

How to use POST method in Tornado?

I'm trying to use Tornado to start a server and post a string to it. I've found lots of examples of how to write the post method in the handler class, but no examples of how to write the post request. My current code does cause the post method to execute, but get_argument isn't getting the data--it just prints the default "No data received" every time. What am I doing wrong?

My code looks like this:

class MainHandler(tornado.web.RequestHandler):
    def post(self):
        data = self.get_argument('body', 'No data received')
        self.write(data)

application = tornado.web.Application([
    (r"/", MainHandler),
])

if __name__ == "__main__":

    def handle_request(response):
        if response.error:
            print "Error:", response.error
        else:
            print response.body
        tornado.ioloop.IOLoop.instance().stop()

    application.listen(8888)    
    test = "test data"
    http_client = tornado.httpclient.AsyncHTTPClient()
    http_client.fetch("http://0.0.0.0:8888", handle_request, method='POST', headers=None, body=test)
    tornado.ioloop.IOLoop.instance().start()

Is putting the string I want to send in the "body" parameter the right thing to do? In some examples I've seen, like here, it seems people create their own parameters, but if I try to add a new parameter to the request, like

http_client.fetch("http://0.0.0.0:8888", handle_request, method='POST', headers=None, data=test)

I just get an error saying "TypeError: init() got an unexpected keyword argument 'data'"

Thanks!

Upvotes: 23

Views: 47692

Answers (1)

Theron Luhn
Theron Luhn

Reputation: 4082

it seems people create their own parameters

Not quite. From the docs:

fetch(request, **kwargs)

Executes a request, returning an HTTPResponse.

The request may be either a string URL or an HTTPRequest object. If it is a string, we construct an HTTPRequest using any additional kwargs: HTTPRequest(request, **kwargs)

(Link)

So the kwargs are actually from this method.

Anyways, to the real meat of the problem: How do you send POST data? You were on the right track, but you need to url encode your POST data and use that as your body kwarg. Like this:

import urllib
post_data = { 'data': 'test data' } #A dictionary of your post data
body = urllib.urlencode(post_data) #Make it into a post request
http_client.fetch("http://0.0.0.0:8888", handle_request, method='POST', headers=None, body=body) #Send it off!

Then to get the data:

data = self.get_argument('data', 'No data received')

Upvotes: 40

Related Questions