Flask 源碼解析:響應
原文:http://cizixs.com/2017/01/22/flask-insight-response
全文約 10700 字,讀完可能需要 16 分鐘。
這是 flask 源碼解析系列文章的其中一篇,本系列已發布文章列表:
flask 源碼解析:簡介
flask 源碼解析:應用啟動流程
flask 源碼解析:路由
flask 源碼解析:上下文
flask 源碼解析:請求
response 簡介
在 flask 應用中,我們只需要編寫 view 函數,並不需要直接和響應(response)打交道,flask 會自動生成響應返回給客戶端。
The return value from a view function is automatically converted into a response object for you. —— Flask docs
我們知道 HTTP 響應分為三個部分: 狀態欄(HTTP 版本、狀態碼和說明)、頭部(以冒號隔開的字元對,用於各種控制和協商)、body(服務端返回的數據)。比如下面訪問博客首頁的響應:
flask 自然也會提供所有這些數據的操作,視圖函數就支持返回三個值:第一個是返回的數據,第二個是狀態碼,第三個是頭部字典。比如:
這篇文章就講講這背後的魔法。
flask 響應(response)
在flask 源碼解析:應用啟動流程的最後,我們講到 在調用路由到視圖函數之後,會調用 進行最後的處理,在這個方法里就包含了 response 對象的生成和處理邏輯。
的代碼如下:
裡面有兩個方法調用: 根據視圖函數的返回值生成 response 對象, 對 response 做一些後續的處理(比如執行 hooks 函數)。我們先來看看 :
是視圖函數能返回多個不同數量和類型值的關鍵,因為它能處理這些情況,統一把它們轉換成 response。 如果返回值本身就是 Response 實例,就直接使用它;如果返回值是字元串類型,就把它作為響應的 body,並自動設置狀態碼和頭部信息; 如果返回值是 tuple,會嘗試用 (response, status, headers) 或者 (response, headers) 去解析。
NOTE:因為視圖函數可以返回 對象,因此我們可以直接操作 。
不管視圖函數返回的是什麼,最終都會變成 對象,那麼我們就來看看 的定義:
Flask 的 類非常簡單,它只是繼承了 ,然後設置默認返回類型為 html。 不過從注釋中,我們得到兩條很有用的信息:
一般情況下不要直接操作 對象,而是使用 方法來生成它
如果需要使用自定義的響應對象,可以覆蓋 flask app 對象的 屬性。
繼續,下面就要分析 werkzeug 對應的代碼了。
werkzeug response
werkzeug 實現的 response 定義在 文件中:
和我們在flask 請求分析的 Request 類一樣,這裡使用了 Mixin 機制。 精簡後的大概框架如下:
有一些類屬性,定義了默認的值,比如默認字元編碼是 utf-8,默認狀態碼是 200 等。實例化的時候接受的參數有:
response: 字元串或者其他 iterable 對象,作為響應的 body
status: 狀態碼,可以是整數,也可以是字元串
headers: 響應的頭部,可以是個列表,也可以是 對象
mimetype: mimetype 類型,告訴客戶端響應 body 的格式,默認是文本格式
content_type: 響應頭部的 內容
所有這些參數都是可選的,默認情況下會生成一個狀態碼為 200,沒有任何 body 的響應。status、status_code 作為 的屬性,可以直接讀取和修改。body 數據在內部保存為 iterable 的類型, 但是對外也提供了直接讀寫的介面 :
body 字元的編碼和長度都是自動設置的,用戶不需要手動處理。
至於頭部的存儲,werkzeug 使用的是類似於字典的 類。在flask 源碼解析:請求這篇文章中,我們沒有詳細 解釋頭部的存儲,那麼這篇文章就具體分析一下吧。
這個類的提供了很多和字典相同的介面:keys、values、iterms,但是和字典的區別在於它保存的值是有序的,而且允許相同 key 的值存在。 為什麼這麼設計呢?因為著更符合 HTTP 頭部的特性。先來看看有序,在 HTTP 傳送的過程中,如果頭部各個 key-value 鍵值對順序發生變化,有些代理或者客戶端等組件會認為請求被篡改而丟棄或者拒絕請求的處理,所以最好把頭部設置為有序的,用戶按照什麼順序設置的,就按照什麼順序存儲;再說說相同 key 的問題,這是因為 HTTP 頭部同一個 key 可能有多個 value(比如 Accept、SetCookie 頭部)。那麼這個看起比較特殊的字典是怎麼實現的呢?來看代碼:
可以看到,頭部信息在內部存儲為二元組構成的列表,這樣就能同時保證它的有序性和重複性。一個核心的方法是 ,它定義了如何獲取頭部中的信息:
通過下標 ,直接返回對應未知存儲的鍵值對元組
通過 key,返回 value ,返回匹配的第一個 value 值
通過 slice ,返回另外一個 對象,保存了 slice 中所有的數據
然後實現 、 、 、 等方法讓它表現出來字典的特性,除此之外還有 、 、 等和字典無關的方法方便操作。
自定義 response
如果需要擴展 flask 的功能,或者乾脆把它替換掉,只要修改 flask app 的 屬性就可以了,比如:
更多可能的用法,可以參考文章末尾的參考資料。
參考資料
customizing the flask response class
題圖:pexels,CC0 授權。
點擊展開全文
※如何從開發者成長為雲端架構師
※Flask 源碼解析:請求
※Flask源碼解析:上下文
※爬蟲進階:反爬策略的應對機制
TAG:編程派 |
※解決WinForm中UI不響應問題
※Windows 10 更新導致 Visual Basic 應用程序停止響應
※淺析requests庫響應對象的text和content屬性
※Global Change Biology:土壤自養呼吸和異養呼吸對增溫的響應不同
※Google要求發布者添加Nosniff響應標題
※LG 推出 UltraGear Nano 顯示器:採用 1ms 響應時間的 IPS 面板
※蘋果證實 iOS 源代碼泄露強調對 iPhone 安全沒有影響;Chrome 難抵惡意下載攻擊數秒內耗盡資源失去響應
※Android P取消應用無響應提示,將直接關閉
※React不是真正的響應式編程,Svelte才是
※nginx log記錄請求響應時間
※Servlet 伺服器 HTTP 響應
※HTC Vive Pro新版Link Box曝光;Oculus將公開「響應式屏幕」研究成果
※關於使用fastjson統一序列化響應格式
※微軟正在提升Cortana響應對話能力
※響應稅調政策:蘋果iPhoneX/iPad等產品竟全線降價了!
※「刪除Facebook」行動爆發 明星們積極響應
※基於springboot實現http響應異常信息國際化
※Silicon Designs推出專為零到中頻測量而設計的MEMS直流響應加速度計
※LG發布UltraGear Nano IPS電競顯示器新品:1ms響應 175Hz刷新率
※AT&T計劃收購AlienVault,加強網路威脅檢測與響應服務