このサイトは、只今WEB業界で活躍中のデザイナー、プログラマーの方々の情報を集めたweb統合情報サイトです。

Archives Details

Rust – Actix Web × MongoDB環境をサクッと起動

Rust

2024.01.18

どもです。

昨年より業務でガッツリRustでの開発を行ってはいるのですが、主にクライアントアプリ開発の方で、そういえばサーバー周りはどうなっているのだろうと、最近はもごもご漁っている状況だったりします。

Rustのasync対応も終わり、サーバーフレームワークの方も安定且つ、増えて来ている状況で、全然Rustでのサーバー開発はアリだなと感じている今日このごろです。

というか、サーバー開発で使わない理由の少なさもあって、むしろ積極的にサーバー開発にRust採用していくべきだと思いますし、今後も増えていくのだろうと肌感で感じました。

という訳で、今日は、RustのサーバーフレームワークのActix Webを用いて、DBはmongodbでローカル開発環境をサクッと起ち上げて行きたいと思います。

 

HomebrewでMongoDBをインストール

HomebrewでMongoDBをインストールしていきます。この辺解説は割愛させていただきます。

brew tap mongodb/brew
brew install mongodb-community

バーションの確認

mongod --version

起動・停止方法の確認

brew services start mongodb-community
brew services stop mongodb-community

 

MongoDB compassでDB作成

MongoDBのGUIツールのMongoDB compassをインストールしましょう。

こちらは任意でインストールしていただければと。cliで行う方は飛ばして頂いて問題ありません。

MongoDB compass公式のHPよりcompassをインストールしていきます。

ダウンロードページは以下になります。該当するPlatformを選択しダウンロードしましょう。

ダウンロードページ

brewコマンドでmongodbを起動しましたら、MongoDB compass「mongodb://localhost:27017」で接続。+アイコンでデータベース「myApp」を作成、左上の「+ Create collection」ボタンを押下、Collection Name「users」で、「Create collection」ボタンを押下。

これで、DB名「myApp」、collectionは「users」の形で、準備が完了。

 

Actix Web

それでは、Actix Webとmongodbを用いて、APIを作っていきます。

まずは、cargo newで新規プロジェクト作成。

cargo new mongodb --bin

createは以下の3つを使用します。

[dependencies]
mongodb = "2"
actix-web = "^4"
serde = { version = "^1", features = ["derive"] }

プログラムを書いて行くのですが、Actix Webはサンプルが豊富で、mongodbを用いたサンプルも以下に存在します。なので、ソースだけ知りたい方は、こちらを見ていただければと。

GitHub

actix/examples

examplesのソースを追っていきましょう。まずは「src/model.rs」ですが、struct Userを定義しております。

User Model: src/model.rs

pub struct User {
    pub first_name: String,
    pub last_name: String,
    pub username: String,
    pub email: String,
}

 

はい。後は「main.rs」となります。createのインポートや、定数を定義しましょう。

先程のDB名、collection名もこちらで定義しております。

src/main.rs

mod model;

use actix_web::{get, post, web, App, HttpResponse, HttpServer};
use model::User;
use mongodb::{bson::doc, options::IndexOptions, Client, Collection, IndexModel};

const DB_NAME: &str = "myApp";
const COLL_NAME: &str = "users";

 

Actix Webでは、#[post(“/add_user”)]といったアトリビュートでのAPIの定義を行うことが可能です。以下の場合は /add_userのURIに対して、add_user関数を実行し、ユーザーを作成する処理(API)となります。

mongodbである、clientを引数collectionにアクセスし、ユーザーを作成。失敗したらエラーとなります。

ユーザー作成 POST: /add_user

/// Adds a new user to the "users" collection in the database.
#[post("/add_user")]
async fn add_user(client: web::Data<Client>, form: web::Form<User>) -> HttpResponse {
    let collection = client.database(DB_NAME).collection(COLL_NAME);
    let result = collection.insert_one(form.into_inner(), None).await;
    match result {
        Ok(_) => HttpResponse::Ok().body("user added"),
        Err(err) => HttpResponse::InternalServerError().body(err.to_string()),
    }
}

こちらは、ユーザーを参照するAPIとなります。usernameをURIに含め、DBを探索し該当するユーザーを取得します。

usernameに関してはuniqueとして設定されていますので、重複は想定していなくfind_oneで取得しています。

ユーザー参照 GET: /get_user/{username}

/// Gets the user with the supplied username.
#[get("/get_user/{username}")]
async fn get_user(client: web::Data<Client>, username: web::Path<String>) -> HttpResponse {
    let username = username.into_inner();
    let collection: Collection<User> = client.database(DB_NAME).collection(COLL_NAME);
    match collection
        .find_one(doc! { "username": &username }, None)
        .await
    {
        Ok(Some(user)) => HttpResponse::Ok().json(user),
        Ok(None) => {
            HttpResponse::NotFound().body(format!("No user found with username {username}"))
        }
        Err(err) => HttpResponse::InternalServerError().body(err.to_string()),
    }
}

サーバー起動時にcreate_username_index関数を呼び、ソースコードからDocumentsのusernameに対してindex設定を行っています。

なので、mongodb側でindexを外しユニークでは無くなっていたりすると、エラーとなります。

index処理

create_username_index(&client).await;

/// Creates an index on the "username" field to force the values to be unique.
async fn create_username_index(client: &Client) {
    let options = IndexOptions::builder().unique(true).build();
    let model = IndexModel::builder()
        .keys(doc! { "username": 1 })
        .options(options)
        .build();
    client
        .database(DB_NAME)
        .collection::<User>(COLL_NAME)
        .create_index(model, None)
        .await
        .expect("creating an index should succeed");
}

mainの処理は、mongodbにアクセスと、HttpServer::newでサーバーを起ち上げ、App::new()でmongodbのデータをapp data化。先程のAPIをservice化を行っています。

以下の環境で起動。

サーバー

http://127.0.0.1:8080

MongoDB

mongodb://localhost:27017

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    let uri = std::env::var("MONGODB_URI").unwrap_or_else(|_| "mongodb://localhost:27017".into());

    let client = Client::with_uri_str(uri).await.expect("failed to connect");
    create_username_index(&client).await;

    HttpServer::new(move || {
        App::new()
            .app_data(web::Data::new(client.clone()))
            .service(add_user)
            .service(get_user)
    })
    .bind(("127.0.0.1", 8080))?
    .run()
    .await
}

それでは、cargo runで起動しましょう。

cargo run

API疎通テスト

Postmanを用いてAPI疎通テストを行います。まずは、ユーザー作成したいので、POSTに設定で

URIは「http://127.0.0.1:8080/add_user」入力。

BodyはJSON形式で以下のデータを送信。

ユーザー作成 POST: /add_user

{
    "first_name": "daisuke",
    "last_name": "takayama",
    "username": "takayama_daisuke",
    "email": "webcyou@webcyou.com",
}

エラーが出なければ成功。では、作成したユーザーを取得しましょう。

ユーザー取得はGETで、URIを取得したいユーザー名も含めた「http://127.0.0.1:8080/get_user/takayama_daisuke」を入力。

ユーザー参照 GET: /get_user/{username}

レスポンスに該当するユーザーがJSON形式で返却されれば成功。

{
    "first_name": "daisuke",
    "last_name": "takayama",
    "username": "takayama_daisuke",
    "email": "webcyou@webcyou.com"
}

と、一旦ここまでで起動は成功。

いやぁ。爆速のサーバーが容易に扱える事に喜びを感じております。

引き続きRustのサーバー周りも追っていこうと思います。

ではではぁ。

Comment

Related Article

Rust – Actix Web mongo ユーザー登録 JWT認証

2024.03.24

Rust – Actix Web JWT 認証認可 APIの作成

2024.02.25

Rust – Actix Web × JSON 静的ファイルをAPIで返却

2024.01.19

Rust – Actix Web × MongoDB環境をサクッと起動

2024.01.18

5分で学ぶ RustでWave Function Collapse (波動関数崩壊アルゴリズム)

2024.01.15

LLaMAモデル GGMLフォーマット(llama.cpp)をRustフレームワーク Leptosを用いて M1MacMiniでサクッと動かす。

2024.01.11

M1Macで行う「RUSTではじめるOpenGL」

2023.02.25

CATEGORY LIST

LATEST NEWS

Rust - Actix Web mongo ユーザー登録 JWT認証

Rust

2024.03.24

Rust - Actix Web JWT 認証認可 APIの作成

Rust

2024.02.25

Rust - Actix Web × JSON 静的ファイルをAPIで返却

Rust

2024.01.19

Rust - Actix Web × MongoDB環境をサクッと起動

Rust

2024.01.18

5分で学ぶ RustでWave Function Collapse (波動関数崩壊アルゴリズム)

Rust

2024.01.15

LLaMAモデル GGMLフォーマット(llama.cpp)をRustフレームワーク Leptosを用いて M1MacMiniでサクッと動かす。

Rust

2024.01.11

2024年 狙っているモバイルノートPC

tool

2024.01.07

MacOS XcodeにSDL2を追加

tool

2023.12.26

php 7.4にアップデート

PHP

2023.12.24

5分で覚える Flutter Flameで作る Wave Function Collapse - 波動関数崩壊アルゴリズム

AI・Bot・algorithm

2023.12.20

Flutter - Flameでゲーム作成 (キャラクターの移動)

Flutter

2023.07.23

Flutterで作る ChatGPT Prompt Manager

Flutter

2023.07.12

RANKING

Follow

SPONSOR

現在、掲載募集中です。



Links

About Us

WEBデザイナーの、WEBデザイナーによる、WEBデザイナーの為のサイト。「みんなで書こう!」と仲間を募ってみたが、結局書くのは自分だけとなってしまいました。日々のメモを綴っていきます。

Entry Profile

Graphical FrontEnd Engineer
- Daisuke Takayama

MAD CITY 北九州市で生まれ育つ。20代はバンド活動に明け暮れ、ふと「webデザイナーになりたい。」と思い、デジタルハリウッド福岡校入学。卒業後、数々の賞を受賞、web業界をざわつかせる。
現在、主に、ゲーム制作中心に港区六本木界隈で活動中。

FOLLOW US