tags: python
, wsgi
, gunicorn
, uwsgi
Python WSGI及其應用
WSGI是什麼?
- 全名Python Web Server Gateway Interface
- 基於CGI
- Python用來描述了伺服器和請求處理程式之間傳輸資料的一種標準(協議)
PEP3333
基本原理跟目標
server、app、framework共用的界面
…proposes a simple and universal interface between web servers and web applications or frameworks: the Python Web Server Gateway Interface (WSGI).
不再重造輪子
…the goal of WSGI is to facilitate easy interconnection of existing servers and applications or frameworks, not to create a new web framework
只會支援python既有的release
…precludes WSGI from requiring anything that is not already available in deployed versions of Python
未來會增加部署的標準
…current version of WSGI does not prescribe any particular mechanism for “deploying” an application for use with a web server or server gateway. At the present time, this is necessarily implementation-defined by the server or gateway
概要
WSGI分成server端及application端
The WSGI interface has two sides: the “server” or “gateway” side, and the “application” or “framework” side.
server端決定物件(凡是可呼叫的)如何定義
The server side invokes a callable object that is provided by the application side.
…how that object is provided are up to the server or gateway
或者藉由中介元件決定
it is also possible to create “middleware” components that implement both sides of this specification
不管怎樣,server端只呼叫這個物件
Callables are only to be called, not introspected upon
HTTP使用bytes
對Python來說,str
比較好用,根據版本差異str
可以是bytes(Python2)或unicode(Python3)實作而來,因此str
到bytes須要有個穩定的轉換
…in many Python versions and implementations, strings are Unicode, rather than bytes. This requires a careful balance between a usable API and correct translations between bytes and text in the context of HTTP
…an object of type str, whether it is internally implemented as bytes or unicode. Where you see references to “bytestring”, this should be read as “an object of type bytes under Python 3, or type str under Python 2”.
應用程式端
必須是可反覆呼叫的物件
1 2 3 4 5 6 7 8 9 |
HELLO_WORLD = b"Hello world!\n" def simple_app(environ, start_response): """最簡易的方式,用函式來實作""" status = '200 OK' response_headers = [('Content-type', 'text/plain')] start_response(status, response_headers) return [HELLO_WORLD] |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
HELLO_WORLD = b"Hello world!\n" class AppClass: """用類別來實作""" def __init__(self, environ, start_response): self.environ = environ self.start = start_response def __iter__(self): status = '200 OK' response_headers = [('Content-type', 'text/plain')] self.start(status, response_headers) yield HELLO_WORLD def __call__(self): """如果想要回傳類別實例,要實作__call__,因為回傳的物件必須是callable""" pass |
伺服器端
主要是迴圈輸出應用程式物件所回傳的結果,並事先將結果轉換成bytes
兩端溝通的延伸:中介(Middleware)物件
可以實現多項自訂功能:
- 根據request url回傳相對的應用程式物件
- 允許異步執行應用程式物件
- 負載平衡
- 修改content
編碼問題
伺服器端只接受bytes,unicode在應用程式端自行處理
HTTP does not directly support Unicode, and neither does this interface. All encoding/decoding must be handled by the application; all strings passed to or from the server must be of type str or bytes, never unicode.
錯誤處理
applications should try to trap their own, internal errors, and display a helpful message in the browser.
Servers should trap and log any exception that aborts an application or the iteration of its return value.
其他HTTP功能
伺服器端跟應用程式端的關係應該像閘道伺服器跟源伺服器
In a sense, a server should consider itself to be like an HTTP “gateway server”, with the application being an HTTP “origin server”.
gateways should “play dumb” and allow the application complete control over its output
Similarly, a server may re-encode or transport-encode an application’s response, but the application should use a suitable content encoding on its own, and must not apply a transport encoding. A server may transmit byte ranges of the application’s response if requested by the client, and the application doesn’t natively support byte ranges.