Search code examples
pythondebugginghttpwebtornado

Tornado - How to get response of AsynHTTPClient.fetch()?


#!/usr/bin/env python

import tornado.httpserver
import tornado.ioloop
import tornado.options
import tornado.web
import tornado.httpclient

import urllib
import json
import datetime
import time

from tornado.options import define, options
define("port", default=8000, help="run on the given port", type=int)

config = {
        'proxy_host': '58.59.21.228',
        'proxy_port': 25,
        'proxy_username': 'yz',
        'proxy_password': 'fangbinxingqusi',
}

def handle_request(response):
    if response.error:
        print "Error:", response.error

tornado.httpclient.AsyncHTTPClient.configure("tornado.curl_httpclient.CurlAsyncHTTPClient")

class IndexHandler(tornado.web.RequestHandler):
    def get(self):
        client = tornado.httpclient.AsyncHTTPClient()
        response = client.fetch("http://twitter.com/", handle_request,
                **config)
        self.write(response.body)

if __name__ == "__main__":
    tornado.options.parse_command_line()
    app = tornado.web.Application(handlers=[(r"/", IndexHandler)],
            debug=True)
    httpserver = tornado.httpserver.HTTPServer(app)
    httpserver.listen(options.port)
    tornado.ioloop.IOLoop.instance().start()

At running, response object in the get() method is reported to be a None type. How can I get the response of the fetch() method in the get() method?


Solution

  • You are using the AsyncHTTPClient, therefore the fetch method does not return anything. You need to use the "asynchronous" decorator and remember to call finish in the callback called by fetch.

    Here is the code:

    import tornado.httpserver                                                    
    import tornado.ioloop                                                        
    import tornado.options                                                       
    import tornado.web                                                           
    import tornado.httpclient                                                    
    
    from tornado.options import define, options                                  
    define("port", default=8000, help="run on the given port", type=int)         
    
    config = {                                                                   
        'proxy_host': '58.59.21.228',                                            
        'proxy_port': 25,                                                        
        'proxy_username': 'yz',                                                  
        'proxy_password': 'fangbinxingqusi',                                     
    }                                                                            
    
    tornado.httpclient.AsyncHTTPClient.configure("tornado.curl_httpclient.CurlAsyncHTTPClient")
    
    
    class IndexHandler(tornado.web.RequestHandler):                              
    
        @tornado.web.asynchronous                                                
        def get(self):                                                           
            client = tornado.httpclient.AsyncHTTPClient()                        
            client.fetch("http://twitter.com/", self.handle_request, **config)   
    
        def handle_request(self, response):                                      
            if response.error:                                                   
                print("Error:", response.error)                                  
            else:                                                                
                self.write(response.body)                                        
            self.finish()                                                        
    
    
    if __name__ == "__main__":                                                   
        tornado.options.parse_command_line()                                     
        app = tornado.web.Application(handlers=[(r"/", IndexHandler)], debug=True)
        httpserver = tornado.httpserver.HTTPServer(app)                          
        httpserver.listen(options.port)                                          
        tornado.ioloop.IOLoop.instance().start()             
    

    You can also use Tornado's gen to make your handler prettier:

    class IndexHandler(tornado.web.RequestHandler):                              
    
        @tornado.web.asynchronous                                                
        @tornado.gen.engine                                                      
        def get(self):                                                           
            client = tornado.httpclient.AsyncHTTPClient()                        
            response = yield tornado.gen.Task(client.fetch, "http://twitter.com/",
                                            **config)                            
            if response.error:                                                   
                self.write("Error: %s" % response.error)                         
            else:                                                                
                self.write(response.body)                                        
    
            self.finish()