6.Tornado RequestHandler和Application類---瞭解web.py文件

前面一小節提到了需要了解 web.py 這個文件,這個文件最關鍵的地方是定義了 Application 和 RequestHandler 類。我們再看看 Tornado 的 Hello World,我們再精簡一下,下面是最簡單的實例化並啓動  Application的方式:

1 import ioloop
2 import web
3  
4 application = web.Application([
5     (r'/', MainHandler),
6 ])
7 application.listen(8888)
8 ioloop.IOLoop.instance().start()

從代碼裏可以看到的是:應用裏定義了 URI 路由和對應的處理類,並以此構建了application對象,然後讓這個對象監聽在8888端口,最後由 ioloop 單例進入循環,不斷分發事件。

這裏的URI路由就是r"/",對應處理類就是 MainHandler,它們被放在同一個 tuple 裏形成了關聯。可以看到,application 是接受一個列表的,因此可以定義多個全局路由對應不同處理,往列表裏 append 就是了。

如果只是在 tornado 的框架基礎上進行開發,那就只需要不斷定義不同的處理類,並把對應路由與其關聯即可。

tornado.web 裏的 RequestHandler 和 Application 類

Tornado 使用 web 模塊的 Application 做URI轉發,然後通過RequestHandler處理請求。 Application 提供了一個 listen 方法作爲 HTTPServer 中的 listen 的封裝。

初始化 Application 時,一般將處理器直接傳入,它會調用 add_handlers 添加這些處理器,初始化還包括 transforms (分塊、壓縮等)、UI模塊、靜態文件處理器的初始化。 add_handlers 方法負責添加URI和處理器的映射。

Application 實現 URI 轉發時使用了一個技巧,它實現了 __call__ 方法,並將 Application 的實例傳遞給 HTTPServer ,當監聽到請求時,它通過調用 Application 實例觸發 __call__ 。 __call__ 方法中完成具體的URI轉發工作,並調用已註冊的處理器的 _execute 方法,處理請求。

01 def __call__(self, request):
02     transforms = [t(request) for in self.transforms]
03     handler = None
04     args = []
05     kwargs = {}
06     handlers = self._get_host_handlers(request) # 取得請求的host的一組處理器
07     if not handlers:
08         handler = RedirectHandler(
09             self, request, url="http://" + self.default_host + "/")
10     else:
11         for spec in handlers:
12             match = spec.regex.match(request.path)  # 匹配請求的URI
13             if match:
14                 handler = spec.handler_class(self, request,**spec.kwargs) # 實例化
15                 if spec.regex.groups:   # 取得參數
16                     ...
17                     if spec.regex.groupindex:
18                         kwargs = dict(
19                             (str(k), unquote(v))
20                             for (k, v) inmatch.groupdict().iteritems())
21                     else:
22                         args = [unquote(s) for in match.groups()]
23                 break
24         if not handler:     # 無匹配
25             handler = ErrorHandler(self, request, status_code=404)
26     ...
27     handler._execute(transforms, *args, **kwargs)   # 處理請求
28     return handler

RequestHandler 完成具體的請求,開發者需要繼承它,並根據需要,覆蓋 head 、 get 、 post 、 delete 、 patch 、 put 、 options 等方法,定義處理對應請求的業務邏輯。

RequestHandler 提供了很多鉤子,包括 initialize 、 prepare 、 on_finish 、 on_connection_close 、 set_default_headers 等等。

下面是 _execute 的處理流程:

RequestHandler 中涉及到很多 HTTP 相關的技術,包括 Header、Status、Cookie、Etag、Content-Type、鏈接參數、重定向、長連接等等,還有和用戶身份相關的XSRF和CSRF等等。這方面的知識可以參考《HTTP權威指南》。

Tornado默認實現了幾個常用的處理器:

  • ErrorHandler :生成指定狀態碼的錯誤響應。
  • RedirectHandler :重定向請求。
  • StaticFileHandler :處理靜態文件請求。
  • FallbackHandler :使可以在Tornado中混合使用其他HTTP服務器。

上面提到了 transform ,Tornado 使用這種機制來對輸出做分塊和壓縮的轉換,默認給出了 GZipContentEncoding 和 ChunkedTransferEncoding 。也可以實現自定義的轉換,只要實現 transform_first_chunk 和 transform_chunk 接口即可,它們由 RequestHandler 中的 flush 調用。

發佈了13 篇原創文章 · 獲贊 7 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章