LoginSignup
28
25

More than 3 years have passed since last update.

この記事は セゾン情報システムズ Advent Calendar 2020 8日目の記事です。

あらすじ

actix-web

Web サーバの hello, world

  1. 適当なディレクトリでコマンドプロンプト起動
  2. cargo new web_hello を実行
  3. web_hello をディレクトリを vscode で開く
  4. Cargo.toml ファイルを開き、dependencies に actix-web = "3.3.2" を追加
  5. 以下コードを main.rs に貼り付け

    use actix_web::{get, web, App, HttpServer, Responder};
    
    #[get("/{id}/{name}/index.html")]
    async fn index(web::Path((id, name)): web::Path<(u32, String)>) -> impl Responder {
        format!("Hello {}! id:{}", name, id)
    }
    
    #[actix_web::main]
    async fn main() -> std::io::Result<()> {
        HttpServer::new(|| App::new().service(index))
            .bind("127.0.0.1:8080")?
            .run()
            .await
    }
    
  6. cargo run を実行

  7. ブラウザを開き http://127.0.0.1:8080/123/namae/index.html にアクセスする

  8. id と name が返される

※ URL のパスを動的に取得できることが確認できます
※ 関数に #[get がついていますが GET であることを表しています

TODO 管理

TODO を取得、登録する API の雛形を作っていきます
全体コードは最後に載せます

crate の追加

json を扱うので関連する crate を追加します

Cargo.toml
[dependencies]
actix-web = "3.3.2"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"

構造体の定義

TODO の構造体を定義し、GET と POST で利用します。
新規登録時は id を自動生成したいので未指定を許容したく Option としています。

#[derive(Debug, Serialize, Deserialize)]
struct Todo {
    id: Option<u32>,
    content: String,
    done: bool,
}

TODO の取得(GET)

構造体を json として返します。
ここで取得した ID を使ってデータベースなどにアクセスする予定です。

#[get("/todos/{id}")]
async fn get_todo(web::Path(id): web::Path<u32>) -> impl Responder {
    println!("get_todo");
    let id_option: Option<u32> = Some(id);
    HttpResponse::Ok().json(Todo {
        id: id_option,
        content: String::from("やること"),
        done: false,
    })
}

TODO の登録(POST)

JSON をリクエストで受け取り、構造体に変換して扱います。

#[post("/todos")]
async fn post_todo(todo: web::Json<Todo>) -> impl Responder {
    println!("post_todo");
    println!("{:?}", todo);
    HttpResponse::Ok().body("ok")
}

コード全体

main.rs
use actix_web::{get, post, web, App, HttpResponse, HttpServer, Responder};
use serde::{Deserialize, Serialize};

#[derive(Debug, Serialize, Deserialize)]
struct Todo {
    id: Option<u32>,
    content: String,
    done: bool,
}

#[get("/todos/{id}")]
async fn get_todo(web::Path(id): web::Path<u32>) -> impl Responder {
    println!("get_todo");
    let id_option: Option<u32> = Some(id);
    HttpResponse::Ok().json(Todo {
        id: id_option,
        content: String::from("やること"),
        done: false,
    })
}

#[post("/todos")]
async fn post_todo(todo: web::Json<Todo>) -> impl Responder {
    println!("post_todo");
    println!("{:?}", todo);
    HttpResponse::Ok().body("ok")
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(|| App::new().service(get_todo).service(post_todo))
        .bind("127.0.0.1:8080")?
        .run()
        .await
}

サーバ起動

cargo run を実行
ブラウザで http://localhost:8080/todos/123 にアクセスする → json が返される
HTTPクライアントなどで http://localhost:8080/todos に以下を POST する → サーバのコンソールに表示される

{
    "content": "なにかやる",
    "done": false
}

まとめ

思ったよりも少ないコードでサーバが書けそうでした
今後は Web アプリケーションや WebAssembly なども触っていきたいと思います。

明日の セゾン情報システムズ Advent Calendar 2020 もお楽しみに!

28
25
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
28
25