RustでWebアプリケーションを作ってみよう

2021-11-28

はじめに

新しい電子レンジを買いました。Amazon Black Fridayのセールで変えたら良いなぁって思ってたやつが、1万引きだったので買いました。 それでも予算からは1万オーバしてたのですが、過熱水蒸気オーブンレンジ機能も付いてるやつを買っちゃいました。 来月のクレジット引き落としが恐ろしいのですが、ボーナス君に願いを託しました。 頼むぞボーナス。ほんと頼むぞボーナス。手違いで1000万ぐらい振り込まれてくれ頼むぞ。

Webフレームワークの導入

せっかくなのでGoなどでやってきたこともRustで試してみたいなという気持ちになっています。 急いでいる人は、【解決】ってやつの対策を取れば、多分治ると思います。

まずはHello Worldを出すところまでをやっていきましょう。

Cargo-editの追加

cargo addを使いたいですが、無いのでcargo-editを導入してツールセットを準備する必要があります。

cargo install cargo-edit    
(中略)
Compiling crates-index v0.17.0
Compiling cargo-edit v0.8.0
 Finished release [optimized] target(s) in 3m 03s
Installing C:\Users\kenpos\.cargo\bin\cargo-add.exe
Installing C:\Users\kenpos\.cargo\bin\cargo-rm.exe
Installing C:\Users\kenpos\.cargo\bin\cargo-set-version.exe
Installing C:\Users\kenpos\.cargo\bin\cargo-upgrade.exe
Installed package `cargo-edit v0.8.0` (executables `cargo-add.exe`, `cargo-rm.exe`, `cargo-set-version.exe`, `cargo-upgrade.exe`)

これでcargo addが使えるようになります。 非同期処理などを行うためのactix-rtと、actix-webを導入します。

cargo add actix-web actix-rt

Webアプリケーションの立ち上げ

Crate actix_web

このサイトにあるExampleを動かして行きます。 とりあえず動かすところを目的にしているのでindex()の関数や、main()関数を少し変更しています。

use actix_web::{web, App, HttpServer, Responder};

async fn index() -> impl Responder {
    format!("Hello")
}

#[actix_rt::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(|| App::new().service(web::resource("/").to(index)))
        .bind("127.0.0.1:8080")?
        .run()
        .await
}

Error: Os { code: 10013, kind: PermissionDenied, message: “アクセス許可で禁じられた方法でソケットにアクセスしようとしました。” }

実際に実行してみるとエラーが出ることがあります。 ポート番号などがすでに使用されている場合、起動に失敗した場合は、このように調べます。

netstat -ano

結果としてはこんな画面になります。 出力結果の中に、指定しされていないポート番号を適当に選んでみましょう。

netstat -ano

アクティブな接続

  プロトコル  ローカル アドレス      外部アドレス           状態            PID
  TCP         0.0.0.0:135            0.0.0.0:0              LISTENING       1200
  TCP         0.0.0.0:445            0.0.0.0:0              LISTENING       4   
  TCP         0.0.0.0:554            0.0.0.0:0              LISTENING       9080
  TCP         0.0.0.0:2179           0.0.0.0:0              LISTENING       2728
  TCP         0.0.0.0:2869           0.0.0.0:0              LISTENING       4   
  TCP         0.0.0.0:3306           0.0.0.0:0              LISTENING       7788
  TCP         0.0.0.0:5040           0.0.0.0:0              LISTENING       5908
  TCP         0.0.0.0:5357           0.0.0.0:0              LISTENING       4   
  (省略)
解決方法

実行するポート番号を変えて上げれば良いです。 例えばこんな感じです。

#[actix_rt::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(|| App::new().service(web::resource("/").to(index)))
        .bind("127.0.0.1:6756")?
        .run()
        .await
}

もし環境変数の設定をしていない状態で実行すると次のようなエラー内容に変わったかと思います。

note: run with RUST_BACKTRACE=1 environment variable to display a backtrace

このエラーをざっくり翻訳すると、「お前、RUST_BACKTRACE=1をつけて実行しろ。俺にこんな事言わせんな。恥ずかしい」となります。

cargo run
   Compiling todolist v0.1.0 (E:\SourceCode\Rust\todolist)
    Finished dev [unoptimized + debuginfo] target(s) in 4.41s
     Running `target\debug\todolist.exe`
thread 'main' panicked at 'System is not running', C:\Users\kenpos\.cargo\registry\src\github.com-1ecc6299db9ec823\actix-rt-1.1.1\src\system.rs:78:21
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
error: process didn't exit successfully: `target\debug\todolist.exe` (exit code: 101)

なので、システム環境変数に設定してあげるとより詳細なエラー無いようが取得できるようになります。

cargo run
    Finished dev [unoptimized + debuginfo] target(s) in 0.35s
     Running `target\debug\todolist.exe`
thread 'main' panicked at 'System is not running', C:\Users\kenpos\.cargo\registry\src\github.com-1ecc6299db9ec823\actix-rt-1.1.1\src\system.rs:78:21
stack backtrace:
(中略)
  54: core::ops::function::FnOnce::call_once<fn() -> enum$<core::result::Result<tuple<>, actix_http::error::Error>, 1, 18446744073709551615, Err>,tuple<>>
             at /rustc/a178d0322ce20e33eac124758e837cbd80a6f633\library\core\src\ops\function.rs:227     
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
error: process didn't exit successfully: `target\debug\todolist.exe` (exit code: 101)

1ってところをfullにすると更に情報が増えます。

【解決方法】 thread ‘main’ panicked at ‘System is not running’, actix-rt-1.1.1\src\system.rs:78:21

情報を増やしてみると見えてくるものがありました。 この手順を動かせば、まずは解消できると思います。

thread 'main' panicked at 'System is not running', C:\Users\kenpos\.cargo\registry\src\github.com-1ecc6299db9ec823\actix-rt-1.1.1\src\system.rs:78:21
stack backtrace:

どうも、system.rsで要求されているのが、actix-rt 1.1.1のようです。 なので、cargo.tomlのactix-rtのバージョンを揃えてあげれば動くようになります。


[dependencies]
actix = "0.12.0"
actix-rt = "1.1.1"
actix-web = "3.3.2"

実行結果

無事数々のエラーを乗り越えWebブラウザからアクセスするとこのような結果が得られます。 お疲れさまでした。

まとめ

蓋を開ければ何でも無い、ライブラリのバージョン違いによるものでしたが、全くわからないまま結構時間をもってかれました。 この記事が、誰かの役に立てば良いなと思いながら残します。

Vueとかと連携していくのもできそうですので、もう少し分かってきたらまた記事にします。