小辣椒開發筆記
應用啟動流程
根據WSGI協議,應用程式會接收到web server提供的environ與start_response兩個引數,我們只需要從environ引數中提取相關資訊並返回一個可迭代物件即可。
flask對該流程的處理邏輯如下:
def wsgi_app(self, environ, start_response):
#根據提供的environ建立請求上下文物件,併入棧
ctx = self.request_context(environ)
ctx.push()
error = None
try:
# 正確的請求處理路徑,會通過路由找到對應的處理函式
response = self.full_dispatch_request()
except Exception as e:
# 錯誤處理,預設是 InternalServerError 錯誤處理函式,客戶端會看到伺服器 500 異常
error = e
response = self.handle_exception(e)
return response(environ, start_response)
首先對出入的environ引數建立一個RequestContext請求上下文物件,該物件包含著HTTP請求所含有的所有資訊。之後請求上下文建立成功後,會執行response = self.full_dispatch_request()
,該語句會根據請求中的路由找到相應的處理函式來處理請求,並將該函式的返回值處理後生成response物件返回。在處理請求的過程中,若遇到了異常,則該異常會被捕獲並交給handle_exception(e)
函式處理,該函式接受一個異常物件並返回一個response物件。之後獲取response物件後,呼叫該物件即可。(所以說我們的應用程式好像更像是一箇中介軟體?)
路由處理
def dispatch_request(self):
rule = request.url_rule
return self.view_functions[rule.endpoint](**request.view_args)
由路由到函式的對映關係為路由->端點->函式
,在werkzeug庫中已經提供了一系列的類供我們處理路由與端點的關係,而我們需要做的只是處理端點到函式的對映關係,該關係用一個字典即可輕鬆搞定。由程式碼可知我們會在生成request物件的時候根據路由獲取對應的端點,在處理請求的時候我們只需根據端點呼叫相應函式即可。而對於端點與函式的對映關係,我們提供了一個簡單的函式用於註冊:
def add_url_rule(self, path, view_func, endpoint=None, methods=None):
if endpoint is None:
endpoint = view_func.__name__
if methods is None:
methods = getattr(view_func, "methods", None) or ("GET",)
rule = Rule(path, endpoint=endpoint, methods=methods)
self.url_map.add(rule)
self.view_functions[endpoint] = view_func
異常處理
def handler_exceptions(self, e):
exc_type = type(e)
if exc_type in self.handler_map:
handler = self.handler_map.get(exc_type)
return handler(e)
else:
raise e
請求處理過程中觸發異常的話,異常會被捕獲並交給該函式處理,該函式接受一個異常後,根據異常所屬的類檢視該異常的處理方式是否被註冊,若已被註冊,則將該異常拋給註冊的錯誤處理器處理,並返回響應。若未被註冊,則將異常再次丟擲,觸發程式錯誤。用於註冊錯誤處理器的函式如下:
def register_error_handler(self, exc_class_or_code, handler):
exc_class = _find_exceptions(exc_class_or_code)
self.handler_map[exc_class] = handler