本文參考了:
- Wikipedia : Web Server Gateway Interface
- WSGI: The Server-Application Interface for Python
- wsgi.tutorial.codepoint.net/intro
- flask 原始碼解析:應用啟動流程
想要理解wsgi,首先得區分一個概念:server 和 app。
uwsgi、gunicorn是 server,我們寫的 django、flask、sanic 程式是 app。app 就是一個可被呼叫的物件(callable object),server 會解析請求資料傳給 app,app 執行業務邏輯之後,把結果返回給 server。
現實生活中,我們部署的時候,可能還會在 server 前面加上一個 nginx,所以整個流程簡單來說是這樣的:
app 可巢狀 -> 中介軟體
app 是一個可呼叫物件,這意味著我可以在 app1裡面呼叫 app2,app2裡面再呼叫 app3,這樣一層一層巢狀下去。這不就是 middleware 嗎?
如果你看過 django middleware 的原始碼,會看到MiddlewareMixin
這個類:
class MiddlewareMixin:
def __init__(self, get_response=None):
self.get_response = get_response
super().__init__()
def __call__(self, request):
response = None
if hasattr(self, 'process_request'):
response = self.process_request(request)
response = response or self.get_response(request)
if hasattr(self, 'process_response'):
response = self.process_response(request, response)
return response
複製程式碼
定義了一個__call__
方法,它是一個可呼叫物件。
你在 django 配置檔案中定義的:
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
複製程式碼
執行的時候,就是這樣一個一個地呼叫 middleware,直到呼叫到你的業務邏輯程式碼(最終的 app 部分)。
後面會再詳細講講中介軟體開發。
app向server暴露的介面
app 是一個可呼叫的物件,它需要接收一些引數,具體如下:
def app(environ,start_response):
pass
複製程式碼
具體看一下這兩個引數:
- environ,就是一個保護請求資訊的字典。
比如 server 收到GET http://localhost:8000/auth?user=obiwan&token=123
這條請求後,會生成下面這樣一個 environ 字典:
這裡麵包含了此次請求的所有必要資訊,通過這個字典,app就能知道這次請求的 path 是/auth
,於是就知道該呼叫哪個 handler 函式。還能通過 HTTP_COOKIE知道 cookie 值,然後可以定位到具體的使用者。
- start_response(status, headers,errors)
Server 傳給 app 的回撥函式,返回資料給 server 之前需要先呼叫這個回撥函式,通知 server 你該來獲取返回資料了。
聽說這個引數實已經快有被廢棄了,不需要完全瞭解。下圖來源於:WSGI: The Server-Application Interface for Python底部評論區。
如果你像我一樣真正熱愛電腦科學,喜歡研究底層邏輯,歡迎關注我的微信公眾號: