microdot --- 極簡 HTTP 框架¶
Microdot 是一個小巧、受 Flask 啟發的 MicroPython HTTP 框架。它建構於 asyncio 之上,無需執行緒即可處理多個並行用戶端,並提供熟悉的路由裝飾器 API。一個最簡的應用程式看起來像這樣::
from microdot import Microdot
app = Microdot()
@app.route('/')
async def index(request):
return 'Hello, world!'
app.run(host='0.0.0.0', port=80)
class Microdot¶
- class microdot.Microdot¶
一個 HTTP 應用程式實例。通常在指令碼開頭附近建構一個實例,並以路由處理常式加以裝飾;呼叫
run()或 awaitstart_server()即開始提供服務。路由註冊
- route(url_pattern: str, methods: list | None = None) Callable¶
用於為 url_pattern 在所列 HTTP 方法(預設
['GET'])下註冊處理常式的裝飾器。回傳該裝飾器;當套用於某函式時,會將其註冊為處理常式並原樣回傳該函式。- url_pattern
一個路徑模式。支援靜態區段(
/users)以及以</>括起的動態區段。動態區段可接受以:分隔的選用型別前綴 ——<int:id>、<path:rest>、<re:[0-9a-f]+:hex>。預設型別為string。- methods
HTTP 方法名稱清單。若省略,則只比對
GET。
呼叫處理常式時,第一個參數為請求物件,接著以關鍵字引數傳入所有擷取到的動態區段。處理常式的回傳值即成為 HTTP 回應:可以是
Response、字串、元組(body, status_code[, headers]),或字典 / 清單(以 JSON 傳送)。
- get(url_pattern: str) Callable¶
route(url_pattern, methods=['GET'])的便利別名 —— 將被裝飾的函式註冊為 url_pattern 的GET處理常式。回傳該裝飾器。
- post(url_pattern: str) Callable¶
route(url_pattern, methods=['POST'])的便利別名 —— 將被裝飾的函式註冊為 url_pattern 的POST處理常式。回傳該裝飾器。
- put(url_pattern: str) Callable¶
route(url_pattern, methods=['PUT'])的便利別名 —— 將被裝飾的函式註冊為 url_pattern 的PUT處理常式。回傳該裝飾器。
- patch(url_pattern: str) Callable¶
route(url_pattern, methods=['PATCH'])的便利別名 —— 將被裝飾的函式註冊為 url_pattern 的PATCH處理常式。回傳該裝飾器。
- delete(url_pattern: str) Callable¶
route(url_pattern, methods=['DELETE'])的便利別名 —— 將被裝飾的函式註冊為 url_pattern 的DELETE處理常式。回傳該裝飾器。
生命週期掛鉤
- before_request(f: Callable) Callable¶
用於註冊 f 在每個請求之前執行的裝飾器。f 接收請求物件;其回傳值通常會被忽略。若要使請求短路,可回傳一個
Response(或可轉換為其的值)—— 此時管線的其餘部分會被略過,並送出該回應。回傳原樣的 f。
- after_request(f: Callable) Callable¶
用於註冊 f 在每個成功請求之後執行的裝飾器。f 接收
(request, response),並必須回傳(可能已修改的)回應物件。回傳原樣的 f。
- after_error_request(f: Callable) Callable¶
用於註冊 f 在 Microdot 產生錯誤回應(404、500、引發的例外等)之後執行的裝飾器。f 接收
(request, response),並必須回傳(可能已修改的)回應物件。回傳原樣的 f。
- errorhandler(status_code_or_exception_class) Callable¶
用於為某個 HTTP 狀態碼或某個 Python 例外類別註冊自訂處理常式的裝飾器。對於狀態碼,處理常式只接收請求;對於例外類別,則接收
(request, exception)。回傳該裝飾器。
掛載與中止
- mount(subapp: Microdot, url_prefix: str = '', local: bool = False) None¶
將另一個
Microdot實例的路由附掛到 url_prefix 之下。當 local 為False(預設)時,子應用程式的 before / after / error 處理常式也會附掛到父應用程式。當為True時,那些處理常式只會對子應用程式的路由執行。回傳None。
- static abort(status_code: int, reason: str | None = None) None¶
引發
HTTPException以指定狀態碼中止目前的請求。永遠不會正常回傳 —— 框架會捕捉該例外並將其轉換為對應的錯誤回應。在路由主體內使用很方便::from microdot import abort @app.get('/users/<int:id>') def get_user(request, id): user = lookup(id) if user is None: abort(404) return user.to_dict()
執行伺服器
- run(host: str = '0.0.0.0', port: int = 5000, debug: bool = False, ssl=None) None¶
阻塞呼叫端的執行緒,對
start_server()執行asyncio.run()。只有在shutdown()被呼叫且監聽迴圈結束之後才會回傳None。這是啟動獨立應用程式最簡單的方式::app.run(host='0.0.0.0', port=80)
- async start_server(host: str = '0.0.0.0', port: int = 5000, debug: bool = False, ssl=None, start_serving: bool = True) None¶
以協程方式啟動伺服器。當需要與其他任務一起整合進既有的
asyncio事件迴圈時使用此方法。在shutdown()被呼叫之前,此協程不會回傳::async def main(): await asyncio.gather( app.start_server(port=80), capture_loop(), )
- host
要監聽的網路介面。
'0.0.0.0'(預設)表示所有介面;'127.0.0.1'表示僅限回送位址。- port
要監聽的 TCP 連接埠。預設
5000—— 純 HTTP 請選80,HTTPS 則選443。- debug
若為
True,則記錄每個請求並將追蹤回溯傾印到 stdout。- ssl
一個
ssl.SSLContext,用於以 TLS 包裝傳入的連線。None(預設)表示純 HTTP。- start_serving
僅在 CPython 上有意義;在 MicroPython 上會被忽略。
屬性
- before_request_handlers: list¶
以
before_request()註冊的可呼叫物件清單,依註冊順序排列。每一個都會在路由處理常式之前以請求物件執行。直接修改此清單雖可行但很少需要 —— 建議改用裝飾器。
- after_request_handlers: list¶
以
after_request()註冊的可呼叫物件清單,依註冊順序排列。每一個都會在成功的請求之後以(request, response)執行,並必須回傳(可能已修改的)回應。
- after_error_request_handlers: list¶
以
after_error_request()註冊的可呼叫物件清單,依註冊順序排列。每一個都會在錯誤回應產生後(由框架或由應用程式錯誤處理常式產生)以(request, response)執行,並必須回傳該回應。
- error_handlers: dict¶
錯誤鍵到處理常式可呼叫物件的對應,由
errorhandler()填入。鍵可以是 HTTP 狀態碼(int)或 Python 例外類別;值則是已註冊的處理常式。狀態碼處理常式接收(request);例外類別處理常式接收(request, exception)。
class Request¶
- class microdot.Request¶
一個傳入的 HTTP 請求。實例會作為第一個位置引數傳給路由處理常式。應用程式不會直接建構
Request。類別屬性
- max_body_length: int¶
會被緩衝到記憶體中並透過
body公開的最大主體。較大的主體(最多達max_content_length)會保留在 socket 上,必須透過stream讀取。預設 16 KB。
實例屬性
- headers: NoCaseDict¶
請求標頭,以
NoCaseDict表示(不區分大小寫查詢)。
- route: Callable¶
比對到此請求的處理常式函式。
主體存取
- stream: object¶
一個非同步串流物件,透過其在主體上提供
read()。對於大於max_body_length的主體請使用此屬性。
- json: dict | list | str | int | float | bool | None¶
解析為 JSON 的主體(
dict、list、str、int、float或bool—— 視酬載編碼而定),若Content-Type不是application/json則為None。
- form: MultiDict | None¶
URL 編碼的表單欄位,以
MultiDict表示,或None。對於multipart/form-data,請以microdot.multipart.with_form_data()裝飾該路由。
- files: dict | None¶
上傳的檔案,以
{name: FileUpload}表示,由microdot.multipart.with_form_data()填入。在該裝飾器執行之前為None。
- after_request(f: Callable) Callable¶
註冊一個請求本地的 after-request 掛鉤 —— 在應用程式層級的 after-request 處理常式之後執行,且僅在成功時執行。f 接收
(request, response),並必須回傳(可能已修改的)回應物件。回傳原樣的 f。
class Response¶
- class microdot.Response(body=b'', status_code: int = 200, headers: dict | None = None, reason: str | None = None)¶
一個 HTTP 回應。多數處理常式會回傳 Microdot 自動轉換為
Response的值;當需要自訂標頭或特定狀態碼時,可直接建構一個。- body
回應主體。
str會以 UTF-8 編碼;dict/list會以 JSON 編碼並相應設定Content-Type;bytes會原樣傳送;類檔案物件或非同步產生器則以串流方式傳送。- status_code
數值 HTTP 狀態。預設 200。
- headers
回應標頭的字典(不區分大小寫)。
- reason
自訂原因短語。對 200 預設為
"OK",否則預設為"N/A"。
類別屬性
- default_send_file_max_age: int | None¶
當未提供
max_age時,send_file()所用的Cache-Control: max-age值。None(預設)表示不加 Cache-Control 標頭。
- send_file_buffer_size: int¶
send_file()串流時的區塊大小。預設 1024。
- types_map: dict¶
send_file()用於內容型別推斷的副檔名對 mime-type 對應。對應css、gif、html、jpg、js、json、png、txt、svg。
方法
- set_cookie(cookie: str, value: str, path: str | None = None, domain: str | None = None, expires=None, max_age: int | None = None, secure: bool = False, http_only: bool = False, partitioned: bool = False) None¶
新增一個
Set-Cookie標頭。expires 可以是預先格式化的字串,或具有timetuple()的類datetime物件。回傳None;該標頭會就地附加到此回應上。
- delete_cookie(cookie: str, **kwargs) None¶
設定一個使指定 cookie 立即過期的
Set-Cookie。kwargs接受與set_cookie()相同的選項(path、domain、secure、http_only、partitioned);expires與max_age會被忽略。回傳None;該標頭會就地附加到此回應上。
- classmethod redirect(location: str, status_code: int = 302) Response¶
回傳一個重新導向回應::
@app.get('/old') def old(request): return Response.redirect('/new')
- classmethod send_file(filename: str, status_code: int = 200, content_type: str | None = None, stream=None, max_age: int | None = None, compressed: bool | str = False, file_extension: str = '') Response¶
將檔案系統中的某個檔案以串流方式作為回應主體傳送。若未提供
content_type,會透過types_map由副檔名推斷。compressed=True會設定Content-Encoding: gzip(該檔案必須已是壓縮過的)。警告
filename 會被直接開啟。切勿傳入未經淨化的使用者提供路徑 —— 這麼做會允許任意檔案外洩。
例外¶
class URLPattern¶
- class microdot.URLPattern(url_pattern: str)¶
路由 URL 模式的編譯形式。由
Microdot.route()自動建構;應用程式很少會直接實例化它。
輔助類別¶
- class microdot.MultiDict(initial_dict: dict | None = None)¶
一個可為每個鍵儲存多個值的 dict 子類別。用於查詢字串以及 URL 編碼的表單主體,這些情況下同一個鍵可能出現多次(
?tag=a&tag=b)。
- class microdot.NoCaseDict¶
一個具有不區分大小寫字串鍵的 dict 子類別。用於
Request.headers與Response.headers。
模組層級函式¶
- microdot.abort(status_code: int, reason: str | None = None) None¶
Microdot.abort()的捷徑。永遠不會正常回傳 —— 會引發HTTPException。可透過from microdot import abort匯入。
- microdot.redirect(location: str, status_code: int = 302) Response¶
Response.redirect()的捷徑。可透過from microdot import redirect匯入。
- microdot.send_file(filename: str, **kwargs) Response¶
Response.send_file()的捷徑。
- microdot.urlencode(s: str) str¶
對 URL 元件進行百分比編碼。將在 URL 中具有保留意義的字元(
/、?、&、=、#、空格 ...)替換為其%xx十六進位逸出,使結果能安全地置於路徑區段或查詢值之中。回傳編碼後的str。
- microdot.urldecode(s: str) str¶
對 URL 元件進行百分比解碼 —— 即
urlencode()的逆運算。%xx逸出會被替換為其所編碼的位元組,而+會被轉換為空格(歷史上的查詢字串慣例)。回傳解碼後的str。