型安全な情報抽出
Actix Webは、型安全なリクエスト情報アクセスのための機能として、エクストラクタ(すなわちimpl FromRequest
)を提供します。Actix Web 標準エクストラクタの実装が多く用意されています。(implementorsを参照)
エクストラクタは、ハンドラ関数の引数としてアクセスすることができます。Actix Web は、ハンドラ関数ごとに最大12個のエクストラクタをサポートします。引数の位置は順不同です。
パス(Path)
Pathは、リクエストのパスから抽出された情報を提供します。抽出可能なパスの部分は"動的セグメント(dynamic segments)"と呼ばれ、波括弧(curly braces)でマークされています。パスから任意の動的セグメントをデシリアライズすることができます。
たとえば、/users/{user_id}/{friend}
というパスで登録したリソースに対しては、 user_id
と friend
というふたつのセグメントをデシリアライズします。これらのセグメントは、宣言された順にタプルとして取り出すことができます (例: Path<(u32, String)>
)。
また、動的セグメント名とフィールド名をマッチングさせることで、serde
から Deserialize
トレイトを実装した型へのパス情報を抽出することも可能です。以下は、タプル型の代わりに serde
を使用した、同等の例です。
型安全ではないものの代替として、ハンドラ内でパス引数の名前で リクエストを問い合わせることもできます。(match_info
docsを参照。)
クエリ(Query)
Query<T>
型は、リクエストのクエリパラメータを抽出する機能を提供します。その下にはserde_urlencoded
クレートが使用されています。
JSON
Json<T>
は、リクエストボディを構造体にデシリアライズすることができます。リクエストのボディから型付けされた情報を取り出すには、型 T
が serde::Deserialize
を実装している必要があります。
エクストラクタのなかには、 抽出処理を設定する方法を提供しているものがあります。エクストラクタを設定するには、リソースの .app_data()
メソッドにその設定オブジェクトを渡します。Json エクストラクタの場合、JsonConfig が返されます。JSONペイロードの最大サイズと、カスタムエラーハンドラ関数を設定することができます。
次の例では、ペイロードのサイズを4kbに制限し、カスタムエラーハンドラを使用しています。
URLエンコードされたフォーム
URLエンコードされたフォームの body 部分は、Json<T>
のような構造体に抽出することができます。この型は、serde::Deserialize
を実装する必要があります。
FormConfigでエクストラクタ処理を設定することができます。
その他
Actix Webは他にも多くのエクストラクタを提供していますが、ここでは重要なものをいくつか紹介します。
Data
- アプリケーションのステートにアクセスするHttpRequest
-HttpRequest
はそれ自体がエクストラクタであり、リクエストの他の部分にアクセスする必要がある場合に備えています。String
- リクエストのペイロードをString
に変換することができます。サンプルコード
アプリのステートエクストラクタ
アプリケーションのステートは、ハンドラから web::Data
エクストラクタでアクセスできます。しかし、ステートは読み取り専用の参照としてアクセスできます。もしステートにミュータブルなアクセスが必要な場合は、それを実装する必要があります。
以下は、処理されたリクエストの数を保存するハンドラの例です。
このハンドラは動作しますが、data.count
は各ワーカスレッドで処理されたリクエストの数しか数えません。すべてのスレッドにまたがる総リクエスト数を数えるには、shared な Arc
とatomicsを使う必要があります。
注意: すべてのスレッドでステート全体を共有したい場合は、Sharedな可変ステートで説明したように、web::Data
と app_data
を使用します。
Mutex
や RwLock
などの同期を実現する為の組込をアプリのステート内で使用する場合は、注意が必要です。Actix Webはリクエストを非同期で処理します。ハンドラ内のcritical sectionが大きすぎたり、.await
ポイントが含まれていたりすると問題です。これが気になる場合は、Tokio's advice on using blocking Mutex
in async codeも読むことをお勧めします。