🦀
AxumでHandlerが自動実装出来ない時
この記事の対象者と目標
- 対象者
- Axumを使い始めたばかりの方
- Handlerトレイト自動実装ができなくて困っている方
- 目標
Handlerトレイト自動実装の条件を理解する
handlerとは
RustでAxumを使っていく上で、ハンドラーは重要な要素の一つです。
Router
と合わせて使用することで、アプリケーションを構築していくことができます。
Handlerトレイト実装条件と注意点
実装条件
Handlerトレイトは基本的には自動的に実装されます。
条件は以下のようになります。
- 非同期関数であること
- 0~16個の
extractors
を引数を取る関数 -
IntoResponse
トレイトを実装したものを返す関数
IntoResponseを実装したもの
IntoResponseを実装したものは&'static str
、String
、Vec<u8>
、StatusCode
、タプル
など様々です 。
詳細はこちらのImplementations on Foreign Types以降に書いてあります。
注意点
特に気を付けるべき点は引数です。
extractorは以下の2つのトレイトを実装したものです。
-
FromRequest
を実装したもの
例)Json<T>
やForm<T>
-
FromRequestParts
を実装したもの
例)Path<T>
やQuery<T>
、Extension<T>
このFromRequest
が時に気を付けなければならなく、FromRequest
を実装したものはhandler関数の引数の一番最後でなければなりません。
実際の定義は以下のようになっています。
impl<F, Fut, S, Res, M, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16> Handler<(M, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16), S> for F
where
F: FnOnce(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16) -> Fut + Clone + Send + 'static,
Fut: Future<Output = Res> + Send,
S: Send + Sync + 'static,
Res: IntoResponse,
T1: FromRequestParts<S> + Send,
T2: FromRequestParts<S> + Send,
T3: FromRequestParts<S> + Send,
T4: FromRequestParts<S> + Send,
T5: FromRequestParts<S> + Send,
T6: FromRequestParts<S> + Send,
T7: FromRequestParts<S> + Send,
T8: FromRequestParts<S> + Send,
T9: FromRequestParts<S> + Send,
T10: FromRequestParts<S> + Send,
T11: FromRequestParts<S> + Send,
T12: FromRequestParts<S> + Send,
T13: FromRequestParts<S> + Send,
T14: FromRequestParts<S> + Send,
T15: FromRequestParts<S> + Send,
// ⚠️ここに注目!!!!
T16: FromRequest<S, M> + Send,
理由はJsonなどはdeserializeなど解析する必要があり、時間がかかるなどが挙げられます。
また独自でextractorを実装するときはFromRequestPartsとして実装する方がいいと思っています。
実装例
- 自動実装成功例
async fn handler(
Path(id): Path<i32>,
State(app_state): State<AppState>,
// Jsonが一番最後にある!!
Json(payload): Json<User>,
) -> impl IntoResponse {
// do something
}
- 自動実装失敗例
async fn handler(
// Jsonが最後にない!!
Json(payload): Json<User>,
Path(id): Path<i32>,
State(app_state): State<AppState>,
) -> impl IntoResponse {
// do something
}
まとめ
Handlerトレイト自動実装には以下の条件がある。
- 非同期関数であること
- 0~16個の
extractors
を引数を取る関数 -
IntoResponse
トレイトを実装したものを返す関数
また、引数についてはJson<T>
、Form<T>
などのFromRequest
を実装したものは関数の引数の一番最後にする必要がある。
Discussion