ys memos

Blog

Rustのaxumで自作structをハンドラー内で使う


rust

2024/08/26


Rustのaxumを使って、自分で作った構造体をハンドラー内で使う方法を紹介します。


Cargo.toml
axum = "0.7.5"
tokio = { version = "1.39.3", features = ["full"] }

ここでは、シンプルなアクセスカウンターを定義しておく。

counterは、Arc<AtomicUsize>でラップしているため、Cloneしたときに共有される。

use std::sync::{
    atomic::{AtomicUsize, Ordering},
    Arc,
};

#[derive(Clone)]
struct AccessCounter {
    counter: Arc<AtomicUsize>,
}

impl AccessCounter {
    pub fn new() -> Self {
        Self {
            counter: Arc::new(AtomicUsize::new(0)),
        }
    }

    pub fn access(&self) -> usize {
        self.counter.fetch_add(1, Ordering::Relaxed)
    }
}

.layer()Extensionを使ってRouterに追加する。

ハンドラー側では、Extension(access_counter): Extension<AccessCounter>とすることで、AccessCounterを使うことができる。

counterがハンドラー間で共有されているのは、Arcでラップしているためである。

use axum::{routing, Extension, Router};

async fn access_count(Extension(access_counter): Extension<AccessCounter>) -> String {
    format!("{}\n", access_counter.access())
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let access_counter = AccessCounter::new();
    let app = Router::new()
        .route("/", routing::get(access_count))
        .layer(Extension(access_counter));
    let litener = tokio::net::TcpListener::bind("localhost:8080").await?;
    axum::serve(litener, app).await?;
    Ok(())
}

以下のように、ハンドラーごとに状態を保持してAccessCounterを使っていることが確認できた。

$ curl localhost:8080
0
$ curl localhost:8080
1
$ curl localhost:8080
2
$ curl localhost:8080
3

ハンドラーの引数にExtensionを記述すると引数が冗長になると思う方は、続きの記事もご覧ください!


関連タグを探す