axum入門 ~axumで簡単にサーバーを作ろう！~


RustでWebサーバーを立てるためのフレームワークとしてaxumがあります。
そんなaxumの使い方を通してRustの構文などに触れていきたいと思います。
(某所でのLTの発表資料のままです…。)

# もくじ

1. axumとは？
1. axumでどうやってサーバーを立てるのか？
1. ハンドラーの実装の仕組み
1. (おまけ)


# そもそもaxumとは？

Rust製のウェブアプリケーションフレームワーク。

基本的にはhttpサーバーを作るためのライブラリ。



## httpサーバーを作るためには

(アプリケーション層では)基本的にはこの機能が出来れてれば十分

- http リクエストを受け取る
- ルーティング
- リクエストからレスポンスを作る
- http レスポンスを送る


## axumでhttpサーバーを作るためには

axumでは何が必要か

- http リクエストを受け取る -> axum(hyper+tower)が用意
- ルーティング -> axumが機能を提供
- リクエストからレスポンスを作る -> axum(tower)が機能を提供
- http レスポンスを送る -> axum(hyper)が用意

## axumでhttpサーバーを作るためには

- ルーティング
- リクエストからレスポンスを作る(関数を作る)

この二つをやればいい！


# axumで実装するには？

```rust
let app = Router::new()
    .route("/", get(root));

async fn root() {}

// run our app with hyper, listening globally on port 3000
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
axum::serve(listener, app).await.unwrap();
```

これだけ！


## ルーター

このパスに来たらどんな関数を実行するかを登録する

```rust
// our router
let app = Router::new()
    .route("/", get(root))
    .route("/foo", get(get_foo).post(post_foo))
    .route("/foo/bar", get(foo_bar));

```

## ハンドラー

リクエストに対してどんなレスポンスを返すかの関数のこと。

```rust
async fn get_foo(
    header: HeaderMap
    query: Query<GetFooQuery>,
    body: Json<GetFooRequestBody>,
) -> Result<(StatusCode, HeaderMap, Json<GetFooResponseBody>)> {
    /**/
} 
```

リクエストとして必要な情報を引数に書き、
レスポンスとして返却するものを戻り値にするだけ！


# 関数を登録するだけで機能するのは？

ある一定のルールを満たした関数なら何でもハンドラーとして登録できる。

-> どうして？



**traitをうまく使っているから！**


## getの実装

```rust
pub fn get<H, T, S>(handler: H) -> MethodRouter<S, Infallible>
where
    H: Handler<T, S>,
    T: 'static,
    S: Clone + Send + Sync + 'static,
```


## getの実装(概略)

```rust
pub fn get<H>(handler: H) -> MethodRouter<_, _>
where
    H: Handler<_, _>,
```

`H` は型パラメータで、型自体がパラメータとして入る
whereには`H`が型として満たすべきものを指定している


## Handler(1) Handlerの定義

```rust
pub trait Handler<T, S>: Clone + Send + Sized + 'static {
    type Future: Future<Output = Response> + Send + 'static;

    // Required method
    fn call(self, req: Request, state: S) -> Self::Future;

    // Provided methods
    fn layer<L>(self, layer: L) -> Layered<L, Self, T, S>
       where L: Layer<HandlerService<Self, T, S>> + Clone,
             L::Service: Service<Request> { ... }
    fn with_state(self, state: S) -> HandlerService<Self, T, S> { ... }
}
```

## Handler(2) Handlerの定義(概略)

```rust
pub trait Handler<T, S>: Clone + Send + Sized + 'static {
    // Required method
    async fn call(self, req: Request, state: S) -> Response;
}
```

traitは基本的には関数の集合
Handler traitを名乗るには、callという関数を用意することを要求している


## Handler(3) Handlerの実装(概略)

axumではHandlerのimplを 型 F に対して定義している

```rust
impl<T1, T2> Handler<(T1, T2)> for F
{ 
    fn call(self, req: Request, state: S) -> Future { ... }
}
```

## Handler(4) Handlerの実装(概略)

axumではHandlerのimplを **FnOnceを実装しているGenerics** に対して定義している

```rust
impl<F, Fut, T1, T2> Handler<(T1, T2)> for F
where F: FnOnce(T1, T2) -> Fut, 
{ 
    fn call(self, req: Request, state: S) -> Self::Future { ... }
}
```
<!-- 
ここでいう"F"は`FnOnce`を実装しているものに対するGenerics.
つまり`FnOnce`を実装している型で特定の引数と特定の戻り値を持っていればいい。 
この例でのimplは引数が二つの関数はなんでも受け入れられる。
-->

## FnOnce

関数やクロージャーは実体のように扱うことができる。
```rust
fn function_1() { ... }
let x = function_1;

let y = || {} // クロージャー
```

条件によって、自動的に`FnOnce`, `FnMut`, `Fn`が実装(impl)され、
関数であるという制約として使うことができる
(これらだけは制約の表現が若干異なる)


## Handler(4) trait制約

実際の定義→　引数と戻り値に制約がある

```rust
impl<F, Fut, S, Res, M, T1, T2> Handler<(M, T1, T2), S> for F
where
    F: FnOnce(T1, T2) -> Fut + Clone + Send + 'static,
    Fut: Future<Output = Res> + Send,
    S: Send + Sync + 'static,
    Res: IntoResponse,
    T1: FromRequestParts<S> + Send,
    T2: FromRequest<S, M> + Send,　
    {/**/}
```

<style scoped>
  li {
    font-size: 30px;
  }
</style>

## Handler(5) FromRequest


最後の引数はBodyから得られる情報を受け取る`FromRequest`が、
それ以外の引数は、その他の`FromRequestParts`が要求される

`FromRequest`: `Bytes`, `Json<T>` [等](https://docs.rs/axum/latest/axum/extract/trait.FromRequest.html)


`FromRequestParts`: `HeaderMap`, `Method`, `Uri`, `Query<T>`, `Version` [等](https://docs.rs/axum/latest/axum/extract/trait.FromRequestParts.html)


## Handler(6) serde

`Json<T>`型は具体的なJsonをデシリアライズした状態で受け取れる

```rust
#[derive(Deserialize)]
pub struct FooRequestBody {
    name: String,
    id: i64,
}
```

```rust
async get_foo(body: Json<FooRequestBody>) -> String {/**/ }
```

`{ "name": "aaa", "id": 10 }`のようなjsonを受け入れるようになる


## Handler(7) IntoResponse

`Response`を作れる状態の型に定義される

`Json<T>`, `Html<T>`, `Redirect`, `Bytes`, `StatusCode` [等](https://docs.rs/axum/latest/axum/response/trait.IntoResponse.html)


`Response`自体もimplしているので自力で作ってもいい


## Handler(8) Future

非同期的に返すための値

最初は`async fn`にしておけば気にしなくていい


##  まとめ

Handlerは大抵のリクエスト、レスポンスの形に合わせて、traitで抽象化して、関数を登録できるようになっている。

[rust doc](https://docs.rs/axum/latest/axum/index.html)を参考にするとどの型が何を実装しているかが見える


# (おまけ)Handler実装で詰まったときは

## 詰まる例(1) FromRequestの場所が最後以外

`Handler`のimplは、`FromRequest`が最後の引数のときだけに受け入れる
順番が逆になっているとコンパイルエラーになる

```rust
impl<F, Fut, S, Res, M, T1, T2, T3> Handler<(M, T1, T2, T3), S> for F
where
    F: FnOnce(T1, T2, T3) -> Fut + Clone + Send + 'static,
    Fut: Future<Output = Res> + Send,
    S: Send + Sync + 'static,
    Res: IntoResponse,
    T1: FromRequestParts<S> + Send,
    T2: FromRequestParts<S> + Send,
    T3: FromRequest<S, M> + Send,
```


## 詰まる例(2) FromRequestになっていない

`Json<T>`は`T: DeserializeOwned`が要求されている
そのためには`T`がライフタイムを持ってはいけない

```rust
#[derive(serde::Deserialized)]
struct NotOwned<'a> {
  borrowed_str : &'a str,
  owned_string: String, 
}
```


## 詰まる例(3) Sendが消える

```
    Fut: Future<Output = Res> + Send,
```

基本的には非同期関数を通常通り書いていればSendになるが…
使うと`Send`が消えるものがある

`Rc`とか、`rand::rngs::ThreadRng`とか、`!Send`になっているものを使うとasyncが`!Send`になる


<style scoped>
　{
    font-size: 30px;
  }
</style>

# (おまけ)ステップアップするなら学ぶこと

## Service

axumは、towerというClient,Serverを作るcrateの上に乗っかているので、
`Service`についてみておくとaxumがどのような原理で動いているかわかる。

## Middleware

これもtowerのLayerの上に成り立っている。
リクエストのフィルター、ログ、認証など
汎用的に拡張できるので学んでおくといいかも
`Extractor`とかも知ることになる