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
を記述すると引数が冗長になると思う方は、続きの記事もご覧ください!