microdot --- 最小限のHTTPフレームワーク

Microdotは、MicroPython向けの小さなFlaskにインスパイアされた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アプリケーションのインスタンスです。スクリプトの先頭付近で1つのインスタンスを構築し、ルートハンドラでデコレートします。run() を呼び出すか start_server() をawaitすると、サービスの提供が始まります。

ルートの登録

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_patternGET ハンドラとして登録します。デコレータを返します。

post(url_pattern: str) Callable

route(url_pattern, methods=['POST']) の便利なエイリアスです -- デコレートした関数を url_patternPOST ハンドラとして登録します。デコレータを返します。

put(url_pattern: str) Callable

route(url_pattern, methods=['PUT']) の便利なエイリアスです -- デコレートした関数を url_patternPUT ハンドラとして登録します。デコレータを返します。

patch(url_pattern: str) Callable

route(url_pattern, methods=['PATCH']) の便利なエイリアスです -- デコレートした関数を url_patternPATCH ハンドラとして登録します。デコレータを返します。

delete(url_pattern: str) Callable

route(url_pattern, methods=['DELETE']) の便利なエイリアスです -- デコレートした関数を url_patternDELETE ハンドラとして登録します。デコレータを返します。

ライフサイクルフック

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

Microdotがエラーレスポンス(404、500、発生した例外など)を生成した後に実行する f を登録するデコレータです。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 の下にアタッチします。localFalse(デフォルト)の場合、サブアプリの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 の場合、すべてのリクエストをログに記録し、トレースバックを標準出力にダンプします。

ssl

受信接続をTLSでラップするための ssl.SSLContext です。None(デフォルト)はプレーンHTTPを意味します。

start_serving

CPythonでのみ関係します。MicroPythonでは無視されます。

shutdown() None

サーバーの正常なシャットダウンを要求します。ルートハンドラから呼び出しても安全です -- ループが終了する前に現在のリクエストが完了します。すぐに戻ります。実際のシャットダウンは処理中のリクエストが完了した後に発生します。

属性

url_map: list

登録されたルートのリストで、(methods, URLPattern, handler, url_prefix, subapp) のタプルとして格納されます。

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) を受け取ります。

debug: bool

サーバーが debug=True で実行されている間は True です。

class Request

class microdot.Request

受信したHTTPリクエストです。インスタンスは最初の位置引数としてルートハンドラに渡されます。アプリケーションが Request を直接構築することはありません。

クラス属性

max_content_length: int

Content-Length がこのバイト数を超えるリクエストを413レスポンスで拒否します。デフォルトは16KBです。

max_body_length: int

メモリにバッファされ、body を介して公開される本文の最大サイズです。これより大きい本文(max_content_length まで)はソケット上に残り、stream を介して読み取る必要があります。デフォルトは16KBです。

max_readline: int

単一のリクエスト行 / ヘッダー行の最大長(バイト単位)です。デフォルトは2KBです。

インスタンス属性

app: Microdot

リクエストを処理する Microdot インスタンスです。

client_addr: tuple

クライアントのアドレスで、(host, port) の形式です。

method: str

HTTPメソッド文字列('GET''POST' など)です。

scheme: str

'http' または 'https' です。

url: str

リクエストURLの完全なパスとクエリ文字列(ホスト以降のすべて)です。

path: str

パス部分のみです。

query_string: str | None

生のクエリ文字列部分、または None です。

args: MultiDict

解析されたクエリ文字列で、MultiDict として格納されます。

headers: NoCaseDict

リクエストヘッダーで、NoCaseDict(大文字小文字を区別しない検索)として格納されます。

cookies: dict

解析された Cookie ヘッダーで、dict として格納されます。

content_length: int

整数の Content-Length 値、または存在しない場合は0です。

content_type: str | None

Content-Type ヘッダーの値、または None です。

g: object

リクエストごとの自由形式のコンテナ(裸のオブジェクト)です。これに属性を割り当てることで、フック間やハンドラ間で値を受け渡すことができます(request.g.user = ...)。

route: Callable

このリクエストにマッチしたハンドラ関数です。

url_prefix: str

ルートがマウントされたプレフィックス、または '' です。

subapp: Microdot | None

マウントされたサブアプリのインスタンス、または None です。

本文へのアクセス

body: bytes

リクエスト本文全体を bytes として表します。本文がストリーミングされている場合は空になります(stream を参照)。

stream: object

本文に対する read() を公開する非同期ストリームオブジェクトです。max_body_length より大きい本文にはこれを使用します。

json: dict | list | str | int | float | bool | None

JSONとして解析された本文(dictliststrintfloatbool -- ペイロードがエンコードするもの)、または Content-Typeapplication/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_content_type: str

明示的に設定されていない場合に使用されるContent-Typeです。デフォルトは 'text/plain' です。

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です。

already_handled: None

レスポンスをすでに直接書き込んだハンドラから返されるセンチネルです(WebSocketアップグレードで使用)。常に None であり、重要なのはその同一性です。

types_map: dict

send_file() がコンテンツタイプの推論に使用する、拡張子からMIMEタイプへのマップです。cssgifhtmljpgjsjsonpngtxtsvg をマッピングします。

メソッド

Set-Cookie ヘッダーを追加します。expires は事前にフォーマットされた文字列、または timetuple() を持つ datetime ライクなオブジェクトです。None を返します。ヘッダーはこのレスポンスにその場で追加されます。

指定したクッキーをただちに期限切れにする Set-Cookie を設定します。kwargsset_cookie() と同じオプション(pathdomainsecurehttp_onlypartitioned)を受け付けます。expiresmax_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=TrueContent-Encoding: gzip を設定します(ファイルはすでに圧縮されている必要があります)。

警告

filename は直接開かれます。サニタイズされていないユーザー提供のパスを決して渡さないでください -- そうすると任意のファイルの漏洩を許してしまいます。

例外

exception microdot.HTTPException

abort() によって発生し、特定のステータスコードでリクエストをショートサーキットします。Microdotはこれをキャッチし、対応するエラーレスポンスに変換します。

status_code: int

返す数値のHTTPステータスコード -- abort() に渡された値です。

reason: str

エラーレスポンスに含める理由フレーズです。abort() に指定されない場合、"<status_code> error"(例: "404 error")がデフォルトになります。

class URLPattern

class microdot.URLPattern(url_pattern: str)

ルートのURLパターンをコンパイルした形式です。Microdot.route() によって自動的に構築されます。アプリケーションが直接インスタンス化することはほとんどありません。

classmethod register_type(type_name: str, pattern: str = '[^/]+', parser: Callable | None = None) None

ルートパターンで使用する新しい動的セグメント型を登録します。None を返します。型はクラスレベルの型レジストリに追加されます。例えば <uuid:...> 型を追加するには:

URLPattern.register_type('uuid', '[0-9a-f-]{36}')

parser はオプションの呼び出し可能オブジェクトで、キャプチャされた文字列をハンドラに到達する前に変換します。

match(path: str) dict | None

path をパターンと照合し、キャプチャされたグループの辞書を返します。マッチしない場合は None を返します。

ヘルパークラス

class microdot.MultiDict(initial_dict: dict | None = None)

キーごとに複数の値を格納するdictのサブクラスです。同じキーが複数回現れることがあるクエリ文字列やURLエンコードされたフォーム本文(?tag=a&tag=b)に使用されます。

get(key, default=None, type: Callable | None = None)

key の最初の値を返します。オプションで type(呼び出し可能オブジェクト)で変換します。キーが存在しないか変換に失敗した場合は default を返し、それ以外の場合は(オプションで変換された)値を返します。

getlist(key, type: Callable | None = None) list

key のすべての値をリストとして返します。オプションで各値を type で変換します。key が存在しない場合は空のリストを返します。

class microdot.NoCaseDict

大文字小文字を区別しない文字列キーを持つdictのサブクラスです。Request.headersResponse.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 の16進エスケープに置き換え、結果をパスセグメントやクエリ値の中に安全に配置できるようにします。エンコードされた str を返します。

microdot.urldecode(s: str) str

URLコンポーネントをパーセントデコードします -- urlencode() の逆です。%xx エスケープはそれがエンコードするバイトに置き換えられ、+ はスペースに変換されます(歴史的なクエリ文字列の慣習)。デコードされた str を返します。

サブモジュール