Rustでサーバ処理を追加する#
Rustでは、ハンドラ関数とルーティング機能を使ってWebリクエストを処理します。Actix Webフレームワークを使えば、エンドポイントごとに異なる処理を簡単に実装できます。
WebアプリケーションではURLのパスに紐づけて処理をすることが多いです。
URLとは、サイトを表示するときにブラウザに指定する文字列のことで、例えば https://ukiuni.com/hello のような文字列です。 {通信方式}://{サーバ名}/{パス} のような形式で出来上がっています。
このパスに、処理を紐付けることで、1つのサーバに色々な処理を依頼できるようになっています。
前提#
もし、Rustプロジェクトが手元になければ、こちらの手順でRustプロジェクトを用意してください。こちらでも簡単なハンドラを作成していますが、Rustの重要な処理なので、こちらで改めて説明しています。
ハンドラとルーティングの追加#
src/main.rs
に新しいハンドラ関数を追加します。以下のようにファイルを更新してください:
use actix_web::{get, web, App, HttpResponse, HttpServer, Responder};
use serde::{Deserialize, Serialize};
use std::time::SystemTime;
#[derive(Serialize)]
struct Message {
text: String,
}
#[derive(Serialize)]
struct OrderMessage {
message: String,
time: String,
}
#[get("/hello")]
async fn hello() -> impl Responder {
let message = Message {
text: "こんにちは!".to_string(),
};
HttpResponse::Ok().json(message)
}
#[get("/oudon")]
async fn order_oudon() -> impl Responder {
// 現在時刻を文字列に変換
let time = SystemTime::now()
.duration_since(SystemTime::UNIX_EPOCH)
.unwrap()
.as_secs()
.to_string();
let order_message = OrderMessage {
message: "おうどんください。".to_string(),
time,
};
HttpResponse::Ok().json(order_message)
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
println!("サーバーを起動します: http://localhost:8080");
HttpServer::new(|| {
App::new()
.service(hello)
.service(order_oudon)
})
.bind("127.0.0.1:8080")?
.run()
.await
}
この例では:
OrderMessage
構造体を定義しています。これはJSON形式で応答するためのデータ構造です。/oudon
パスに対応するorder_oudon
関数を定義しています。- メイン関数内で
App::new()
にこのハンドラを登録しています。
注意点:
- Rustでは、#[get("/oudon")]
のようなアトリビュートを使ってルートを定義します。
- impl Responder
を返すことで、ActixがHTTPレスポンスに変換できることを示します。
- .service()
メソッドで各エンドポイントをアプリケーションに追加します。
パラメータを受け取るハンドラの追加#
URLパスやクエリパラメータを受け取るハンドラも簡単に実装できます。以下の例を見てみましょう:
use actix_web::{get, web, App, HttpResponse, HttpServer, Responder};
use serde::{Deserialize, Serialize};
#[derive(Deserialize)]
struct GreetQuery {
name: Option<String>,
}
#[derive(Serialize)]
struct GreetingResponse {
message: String,
}
#[get("/greet")]
async fn greet(query: web::Query<GreetQuery>) -> impl Responder {
let name = query.name.as_deref().unwrap_or("ゲスト");
let response = GreetingResponse {
message: format!("こんにちは、{}さん!", name),
};
HttpResponse::Ok().json(response)
}
// main関数内に以下を追加
// .service(greet)
この例を main.rs
に追加してみましょう。main
関数内の App::new()
に .service(greet)
を追加するのを忘れないでください:
App::new()
.service(hello)
.service(order_oudon)
.service(greet)
サーバーを起動すると、http://localhost:8080/greet?name=田中
のようなURLでアクセスできるようになります。
HTTPメソッドの指定#
Actixでは、様々なHTTPメソッド(GET, POST, PUT, DELETE など)に対応するマクロが用意されています:
#[get("/resource")] // GETリクエスト
#[post("/resource")] // POSTリクエスト
#[put("/resource")] // PUTリクエスト
#[delete("/resource")] // DELETEリクエスト
例えば、POSTリクエストでJSONデータを受け取る例は以下のようになります:
#[derive(Deserialize)]
struct CreateUser {
username: String,
email: String,
}
#[post("/users")]
async fn create_user(user: web::Json<CreateUser>) -> impl Responder {
// userデータを処理...
HttpResponse::Created().json(format!("ユーザー {} が作成されました", user.username))
}
// main関数内に以下を追加
// .service(create_user)
これで、Rustでのサーバー処理の基本が完成しました。サーバを起動してみましょう:
cargo run
ブラウザで以下のURLにアクセスしてみてください:
- http://localhost:8080/hello
- http://localhost:8080/oudon
- http://localhost:8080/greet?name=あなたの名前
適切なJSONレスポンスが表示されれば成功です!
次は、Rustでデータベースを扱ってみましょう。