22
33import tornado .web
44import tornado .httpclient
5+ import tornado .gen
6+ from tornado .ioloop import IOLoop
7+ from tornado .concurrent import Future
8+
9+ from ioc .extra .tornado .router import TornadoMultiDict
10+
511import mimetypes
612
713class BaseHandler (tornado .web .RequestHandler ):
@@ -32,22 +38,24 @@ def is_finish(self):
3238 def get_header (self , name ):
3339 return self ._headers .get (name )
3440
41+ def get_form_data (self ):
42+ return TornadoMultiDict (self )
43+
3544class RouterHandler (BaseHandler ):
3645 def initialize (self , router , event_dispatcher , logger = None ):
3746 self .router = router
3847 self .event_dispatcher = event_dispatcher
3948 self .logger = logger
4049
50+ @tornado .web .asynchronous
4151 def dispatch (self ):
42- try :
43- self .event_dispatcher .dispatch ('handler.request' , {
44- 'request_handler' : self ,
45- 'request' : self .request
46- })
4752
48- if self .is_finish ():
49- return
53+ result = None
54+ # the handler.request might close the connection
55+ if self .is_finish ():
56+ return
5057
58+ try :
5159 name , parameters , callback = self .router .match (path_info = self .request .path , method = self .request .method )
5260
5361 if self .logger :
@@ -64,7 +72,7 @@ def dispatch(self):
6472 if self .is_finish ():
6573 return
6674
67- event .get ('callback' )(self , ** event .get ('parameters' ))
75+ result = event .get ('callback' )(self , ** event .get ('parameters' ))
6876
6977 if self .is_finish ():
7078 return
@@ -77,6 +85,9 @@ def dispatch(self):
7785 return
7886
7987 except NotFound , e :
88+ if self .logger :
89+ self .logger .critical ("%s: NotFound: %s" % (__name__ , self .request .uri ))
90+
8091 self .set_status (404 )
8192
8293 self .event_dispatcher .dispatch ('handler.not_found' , {
@@ -98,23 +109,35 @@ def dispatch(self):
98109 'exception' : e ,
99110 })
100111
101- if self .is_finish ():
112+ # the dispatch is flagged as asynchronous by default so we make sure the finish method will be called
113+ # unless the result of the callback is a Future
114+
115+ if isinstance (result , Future ):
116+ IOLoop .current ().add_future (result , self .finish )
102117 return
103118
119+ if not self .is_finish ():
120+ self .finish ()
121+
122+ def prepare (self ):
123+ self .event_dispatcher .dispatch ('handler.request' , {
124+ 'request_handler' : self ,
125+ 'request' : self .request
126+ })
127+
128+ def finish (self , * args , ** kwargs ):
104129 self .event_dispatcher .dispatch ('handler.response' , {
105130 'request_handler' : self ,
106131 'request' : self .request ,
107132 })
108133
109- if not self .is_finish ():
110- self .finish ()
134+ super (RouterHandler , self ).finish ()
111135
112136 self .event_dispatcher .dispatch ('handler.terminate' , {
113137 'request_handler' : self ,
114138 'request' : self .request ,
115139 })
116140
117-
118141 def send_file (self , file ):
119142 """
120143 Send a file to the client, it is a convenient method to avoid duplicated code
@@ -124,7 +147,7 @@ def send_file(self, file):
124147 if mime_type :
125148 self .set_header ('Content-Type' , mime_type )
126149
127- fp = open (file , 'r ' )
150+ fp = open (file , 'rb ' )
128151 self .write (fp .read ())
129152
130153 fp .close ()
0 commit comments