
投稿日 2025/3/5
更新日 2025/3/17 ✏
Rust: actixでwebアプリケーションのhelloworld
RustのWebフレームワークactix-webを使ってWebアプリケーションをhelloworldしてみるメモ。
環境
- rustc 1.84.0
- cargo 1.84.0
- Ubuntu 22.04.5 LTS
プロジェクト新規作成
helloworldプロジェクトを新規作成:
$ cargo new helloworld
$ cd helloworld
Appサーバのコーディング
Cargo.toml
[package]
name = "helloworld"
version = "0.1.0"
edition = "2021"
[dependencies]
actix-service = "2.0"
actix-web = "4"
env_logger = "0.11"
log = "0.4"
src/main.rs (Appサーバ)
use actix_web::{
App, HttpRequest, HttpResponse, HttpServer, Responder, Result, get, middleware, web,
};
use log::error;
use std::panic;
/// GET / なRoute ("helloworld"を返すだけ)
#[get("/")]
async fn index(_req: HttpRequest) -> impl Responder {
let result: Result<&str> = Ok("helloworld!");
match result {
// 200ステータスと"helloworld"を返す:
Ok(msg) => HttpResponse::Ok().body(msg),
// BadRequestなステータスを返す場合は以下のように書く: (このコードでは実際にはここは通らないが)
Err(err) => HttpResponse::BadRequest().body(err.to_string()),
}
}
/// GET /oops なRoute (内部でわざとpanicを起こす)
#[get("/oops")]
async fn oops(_req: HttpRequest) -> impl Responder {
panic!("oops!");
// panicが原因でここには到達しない!
#[allow(unreachable_code)]
HttpResponse::Ok().body("never here!")
}
/// 404 NotFound ハンドラ
async fn not_found_handler() -> impl Responder {
HttpResponse::NotFound().body("not found!")
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
// ロガー初期化 (ログlevelは"error")
env_logger::init_from_env(env_logger::Env::new().default_filter_or("error"));
// panicフックにpanic情報ログ処理を記述
// NOTE: この処理は別になくてもいいが、有った方がpanicの調査に便利!
panic::set_hook(Box::new(|info| {
// panic情報を取得
let location = info.location().unwrap();
let payload = info.payload();
// expect("")のパラメータやエラーデータからメッセージ文字列を作成
let mut txt: String = "".to_string();
if let Some(data) = payload.downcast_ref::<&str>() {
txt.push_str(data);
} else if let Some(data) = payload.downcast_ref::<String>() {
txt.push_str(data);
}
// panic情報を表示
let msg = format!(
"panicked at {}:{}:{}: {}",
location.file(),
location.line(),
location.column(),
txt
);
error!("{}", msg);
}));
let server = HttpServer::new(move || {
App::new()
.wrap(middleware::Logger::default())
.wrap(middleware::NormalizePath::new(
middleware::TrailingSlash::MergeOnly,
))
// Routesを設定:
.service(index) // GET / なRouteをセット
.service(oops) // GET /oops なRouteをセット
// Routeが見つからなかった場合はここに来る:
.default_service(web::to(not_found_handler))
});
let server = server.bind(("127.0.0.1", 8080))?;
for addr in server.addrs() {
println!("Listening on: http://{addr}/");
}
server.run().await
}
Appサーバの実行
Appサーバをビルド&実行:
## これだけでデバッグビルド後に実行される:
$ cargo run
Listening on: http://127.0.0.1:8080/
## or リリースビルドで実行したい場合:
$ cargo run --release
Listening on: http://127.0.0.1:8080/
curlでAppサーバのエンドポイントを叩いてみる:
## helloworldを返すだけのエンドポイントをコール:
$ curl 127.0.0.1:8080/
helloworld
## panicを起こすエンドポイントをコール:
$ curl 127.0.0.1:8080/oops
curl: (52) Empty reply from server
curlで/oops
エンドポイントを叩いたことでAppサーバのログに以下のようなpanic情報が出現:
[2025-03-04T02:34:51Z ERROR helloworld] panic "oops!" occurred at src/main.rs: 23
TIPs
ライブリロード
次の手順でコードをライブリロードすることができます。
cargo-watch
モジュールをインストール: (初回のみ)$ cargo install cargo-watch
- src配下のファイルの変更を監視し、変更が検知されたら
cargo run
実行:$ cargo watch -x run -w ./src
END