Rust axumの基本

RustのWebアプリケーションフレームワーク
– active-web: 高速なパフォーマンス
– Rocket: シンプルで直感的なAPIを持つフレームワーク、わかりやすいコーディングスタイル
– axum: シンプルなフレームワークでモジュラ方式でカスタマイズが容易
– warp: 関数型プログラミングの考え方に基づいたWebフレームワーク

Cargo.toml

[dependencies]
axum="0.6.9"
hyper = { version = "0.14", features = ["full"]}
tokio = { version = "1.25", features = ["full"]}
tower = { version = "0.4", features = ["full"]}

hyper: httpライブラリ、tokio:非同期処理ライブラリ、tower:抽象化レイヤーライブラリ

### axumの基本コード
RouterとServerを用意する必要がある

#[tokio::main]
async fn main() {
	let app = axum::Router::new()
		.route("/", axum::routing::get(|| async{ "Hello, World!"}));

    axum::Server::bind(&"192.168.56.10:8000".parse().unwrap())
    	.serve(app.into_make_service())
    	.await
    	.unwrap();
}

axum::Router::newでインスタンスを作成し、routeでルーティングを追加
|| async {表示するテキスト}
await.unwrap()を忘れると処理が終了してしまう

### 複数のルーティング
getで実行する関数は別に定義しておき、それをgetの引数に指定するようにする

#[tokio::main]
async fn main() {
	let app = axum::Router::new()
		.route("/", axum::routing::get(handler_top))
		.route("/other", axum::routing::get(handler_other));

    axum::Server::bind(&"192.168.56.10:8000".parse().unwrap())
    	.serve(app.into_make_service())
    	.await
    	.unwrap();
}

async fn handler_top() -> String {
	"Hello, World!".to_string()
}

async fn handler_other() -> String {
	"This is otehr page...".to_string()
}

### パラメータを利用

#[tokio::main]
async fn main() {
	let app = axum::Router::new()
		.route("/", axum::routing::get(handler_top))
		.route("/usr/:user_id", axum::routing::get(handler_param));

    axum::Server::bind(&"192.168.56.10:8000".parse().unwrap())
    	.serve(app.into_make_service())
    	.await
    	.unwrap();
}

async fn handler_top() -> String {
	"Hello, World!".to_string()
}

async fn handler_param(axum::extract::Path(user_id):
	axum::extract::Path<String>) -> String {
	format!("User ID: {}", user_id)
}

### 複数の値を渡す

async fn main() {
	let app = axum::Router::new()
		.route("/", axum::routing::get(handler_top))
		.route("/usr/:id/:user", axum::routing::get(handler_param));

// 省略

async fn handler_param(axum::extract::Path((id, user)):
	axum::extract::Path<(usize,String)>) -> String {
	format!("User ID: {}. name:{}", id, user)
}

### クエリパラメータの利用

async fn main() {
	let app = axum::Router::new()
		.route("/", axum::routing::get(handler_top))
		.route("/qry", axum::routing::get(handler_param));
// 省略
async fn handler_param(axum::extract::Query(params):
	axum::extract::Query<std::collections::HashMap<String, String>>) -> String {
	format!("id:{}, name:{}.", params["id"], params["name"])
}

### JSONデータの出力
「serde」というパッケージを使用する。serdeは、JSONなど各種データをRustの構造体に変換するための機能を提供する
Cargo.tomlに以下を追記する

serde = { version = "1.0", features = ["derive"]}
serde_json = "1.0"

serdeのSerializeとDeserializeを指定することで、構造体のシリアライズ/デシリアライズが可能になる。
jsonを返すときは、async fn 関数() -> axum::Json{…}

### json形式で指定IDのデータを出力する

use serde::{Serialize, Deserialize};

#[derive(Serialize, Deserialize, Debug)]
struct Mydata {
	name:String,
	mail:String,
	age:u32,
}


#[tokio::main]
async fn main() {
	let app = axum::Router::new()
		.route("/", axum::routing::get(handler_top))
		.route("/json/:id", axum::routing::get(handler_json));

    axum::Server::bind(&"192.168.56.10:8000".parse().unwrap())
    	.serve(app.into_make_service())
    	.await
    	.unwrap();
}

async fn handler_top() -> String {
	"Hello, World!".to_string()
}

async fn handler_json(axum::extract::Path(id):
	axum::extract::Path<usize>) -> axum::Json<serde_json::Value>{
	let data:[Mydata;3] = [
		Mydata {name:String::from("Taro"),
		mail:String::from("taro@yamada"), age:39},
		Mydata {name:String::from("Hanako"),
		mail:String::from("hanako@flower"), age:28},
		Mydata {name:String::from("Sachiko"),
		mail:String::from("sachiko@happy"), age:17},
	];
	let item = &data[id];
	let data = serde_json::json!(item);
	axum::Json(data)
}