###### tags: `Rust` `actix-web` # actix-web 入門 actix 公式 Get Started https://actix.rs/docs/getting-started/ # Hello, world ```rust= use actix_web::{web, App, HttpResponse, HttpServer, Responder}; fn hello() -> impl Responder { HttpResponse::Ok().body("hello world") } fn main() { HttpServer::new(||{ App::new() .route("/", web::get().to(hello)) .route(...) }) .bind("127.0.0.1:8080") // or localhost:8080 .unwrap() .run() .unwrap(); } ``` コードの解説 - use actix_web : インポート & ネームスペースの利用 - fn Hello() -> impl Responder : urlハンドラー - HttpServer::new(closure) : HttpServer オブジェクトを返す。 - 引数は、Appオブジェクトを返すクロージャー(無名関数) - server.bind("ipアドレス:port") : サーバーをipアドレスに紐付け - 戻り地はResultオブジェクトで、unwrap()して結果を処理する - unwrap() : rust標準のResultオブジェクトのメソッド - 結果が Err なら panic() - 結果が OK なら HttpServer オブジェクトを返す - run() : httpserverのアクセス受付を開始。 # actix-webのスタイル ## Request Handler webserverを作るには、まず Request Handler が必要 ```rust= fn hello() -> impl Responder { HttpResponse::Ok().body("hello world") } ``` ie = すなわち 語源はラテン語の id est = that is Request Handler は - 0か、1つ以上のパラメーターをRequestから受け取る - 必ずHttpResponce (impl Responder) を返す ## App アプリケーションのインスタンス。 url と handler を結びつける、いわばrouter HttpServerを作成するとき、 App fuctory (Appを返すクロージャー)を引数にしなければならない ## Atrribute Macro ルートを定義する方法として、 Attribute Macroを使う方法もある ```rust= use actix_web::get; #[get("/hello")] fn index3() -> impl Responder { HttpResponse::Ok().body("Hey there!") } ~~~ App::new() .service(index3) ~~~ ``` #[get("path")] と書くことで、handler をpathと紐付けられる。 おそらく、pythonのデコレーター(関数を引数として、追加機能をつけて関数を返す)と似たような機能 actix_web::web::get ではなく、 actix_web::get に含まれるMacroである。 このハンドラを使うときは `App.route(path, handler)` ではなく `App.service(service)` となる。 チュートリアル中では構文を伝えるため、露骨に冗長な書き方をするが このsyntax sugarのほうが書きやすいと感じたらいつでも使うべきだと推奨されている。 更に学ぶなら、[actix-web-codegen](https://docs.rs/actix-web-codegen/0.1.2/actix_web_codegen/) をみる。 # Auto Reload Webアプリケーションを開発しているときにいちいち再コンパイルするのは効率が悪い。 そこで、以下の binary command を `cargo install` でインストールして再コンパイルを自動化する。 - systemfd - cargo-watch コマンドはこう `cargo install systemfd cargo-watch` systemfd が開かれている外部ソケットを検出するために、ソースコードに一部変更を加える Cargo.toml ```toml= [dependencies] listenfd = "0.3" ``` main.rs ```rust= use actix_web::{web, App, HttpRequest, HttpServer, Responder}; use listenfd::ListenFd; fn index(_req: HttpRequest) -> impl Responder { "Hello World!" } fn main() { let mut listenfd = ListenFd::from_env(); let mut server = HttpServer::new(|| App::new().route("/", web::get().to(index))); server = if let Some(l) = listenfd.take_tcp_listener(0).unwrap() { server.listen(l).unwrap() } else { server.bind("127.0.0.1:3000").unwrap() }; server.run().unwrap(); } ``` 開発サーバーを起動するには、systemfdコマンドを使う `systemfd --no-pid -s http::3000 -- cargo watch -x run`