Python wsgiref 模組原始碼淺析

發表於2016-02-01

SimpleHTTPServer模組提供了建立一個http服務的例子。Python web領域裡卻很少這麼做,而是使用了另外一個協議 — WSGI協議。Python的wisiref模組提供了demo_app,來演示如何使用wsgi協議。

demo_app即是一個標準的wsgi app。它接受兩個引數,一個包含cgi伺服器的環境變數,另外一個引數是一個函式,這個函式也接受兩個函式,一個是http狀態,另外是http協議的header資訊。最後該app返回一個可迭代物件,這個物件即傳送給客戶端的body內容。demo_app有一些對StringIO的操作,這些都是把environ進行格式化輸出。

Python的web框架,都是一個wsgi app。通過自己構造wsgi應用,很容易寫出一個框架的骨架。python定義了wsgi,讓web框架幾乎可以大一統了。下面就來分析,python是如何實現這個協議的。

WSGIServer

python使用WSGIServer和WSGIRequestHandler構建wsgi協議的服務。

WSGIServer繼承HTTPServer,重寫了server_bind彷彿,設定了一些專用的環境變數。比較簡單,我們也知道,Server只是處理socket連線相關的邏輯,RequestHandler才是處理客戶端請求邏輯。

WSGIRequestHandler

WSGIRequestHandler 也不復雜,只有3個方法,get_environ用來設定並返回環境變數的字典,get_stderr用於獲取標準錯誤輸出。handle則是重寫基類BaseRequestHandler的方法。前文我們也提到,handle用於不同協議處理客戶端的入口。

handler

handle方法和BaseHTTPRequestHanler的handle方法所做的類似,解析驗證客戶端的http的request是否合法。不同的在於,此時會繫結一個ServerHandler的例項物件,並把緩衝可讀可寫檔案控制程式碼,環境變數等傳入該類。同時呼叫這個物件的run方法。其實,我們之前定義的app,恰恰就是傳給run方法,通過run方法的包裝,實現wsgi協議的通訊。

BaseHandler 和 ServerHandler

ServerHandler 來自wsgiref的handlers模組,它繼承 BaseHandler類。又一個帶base類。BaseHandler主要用於操作WSGI app。run方法就是在該類定義的。

run方法最重要的就是呼叫自定義的wsgi app,並把在finish_reponse方法中把結果send給客戶端。

finish_response

把可迭代物件資料返回。通過write方法把資料寫入緩衝可寫檔案,然後傳送給客戶端。

send_preamble

finish_response返回http的body是一方面,其中還需要返回http的headers。這個操作分別在wirte方法和finish_content中,它們都呼叫了send_headers方法,send_headers方法由通過呼叫send_preamble構造header資料,並最終通過_write 方法寫入到緩衝可寫檔案中。完成伺服器對客戶端的響應。

wsgiref模組還包含了另外幾個子模組,上面的的內容主要來自 simple_server 和 handler模組,此外還有headers喝validata模組,用於包裝headers和做驗證,暫且忽略了。

wsgi是 python web框架中的標準,實現了wsgi協議就能寫出一個web框架。python的世界裡不少知名的框架。接下來將會探究一下werkzeug和flask的原始碼以及tornado的原始碼。

相關文章