0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Rust and Cloudflare Workers

Last updated at Posted at 2023-10-29

Rust で REST API を実装する方法を調べる。

業務での実践に近い形にするため、Stateful に実装する。

データの保存は、無課金でやりたいので、D1 を使う。Rust + Workers + D1。

Rust の syntax に慣れていないため、Application での利用パターンを繰り返し実装して慣れる。

今回のコードはこちら。

environment

Cloudflare の template を使用する。

Stateful

D1 を準備する。
wrangler で local に D1 のデータを準備する。

wrangler d1 execute test-db \
  --local --command "CREATE TABLE IF NOT EXISTS users ( user_id INTEGER PRIMARY KEY, email_address TEXT, created_at INTEGER, deleted INTEGER, settings TEXT);"

npx wrangler d1 execute test-db \
  --local --command "INSERT INTO users (user_id, email_address, created_at, deleted, settings) VALUES (1, 'maria@example.com', 0, 0, '');"
npx wrangler d1 execute test-db \
  --local --command "INSERT INTO users (user_id, email_address, created_at, deleted, settings) VALUES (999, 'admin@example.com', 0, 0, '');"

npx wrangler d1 execute test-db \
  --local --command "select * from users;"

REST API

  • 実装仕様
    /: 全件取得
    /n: user_id を指定する。
    Router::new()
    .get_async("/:id", |_, ctx| async move {
        let id = match ctx.param("id") {
            Some(value) => value,
            None => {
                eprintln!("Error: id parameter not found");
                "default_id"
            }
        };
        let d1 = ctx.env.d1("DB")?;
        let statement = d1.prepare("select * from users where user_id = ?1");
        let query = statement.bind(&[id.into()])?;
        let res = query.first::<Users>(None).await;
        match res {
            Ok(Some(user)) => {
                let json = serde_json::to_string(&user)
                    .map_err(|e| Error::from(e.to_string()))?;
                Response::ok(json)
            },
            Ok(None) => Response::error("Not Found", 404),
            Err(e) => {
                eprintln!("Database error: {:?}", e);
                Response::error("Internal Server Error", 500)
            },
        }
    })
    .get_async("/", |_, ctx| async move {
        let d1 = ctx.env.d1("DB")?;
        let statement = d1.prepare("select * from users");
        let res = statement.all().await?;
        Response::from_json(&res.results::<Users>().unwrap())
    }).run(request, env).await
vscode ➜ /workspaces/rust-worker (main) $ curl localhost:8787
[{"user_id":1,"email_address":"maria@example.com","created_at":0,"deleted":0,"settings":""},{"user_id":999,"email_address":"admin@example.com","created_at":0,"deleted":0,"settings":"
vscode ➜ /workspaces/rust-worker (main) $ curl localhost:8787/1
{"user_id":1,"email_address":"maria@example.com","created_at":0,"deleted":0,"settings":""}
vscode ➜ /workspaces/rust-worker (main) $ 

Impression

  • Rust の書き方で好感を覚えるのは、match
    if で分岐させる必要はないし、簡潔に書くことが可能。
  • まだ、直感的に書けるところまで来ていない。例えば、namespace の解決や関連関数へのアクセスに用いる :: について、迷う。

GPT-4 コード解説

このRustのコードは、WebAssemblyのために書かれたHTTPリクエストに対応するサーバレス関数を実装しています。クラウドフレアのWorkers(あるいは同様のサーバレスプラットフォーム)で動作することを意図していると思われます。このコードは、特定のエンドポイントへのHTTPリクエストを処理し、データベース(おそらくCloudflare WorkersのD1)からユーザー情報を取得してレスポンスを返します。具体的な部分を説明します。

  1. モジュールとクレートのインポート:
    workerクレートとserdeクレートをインポートしています。workerはWebAssemblyベースのサーバレス環境用のAPIを提供し、serdeはRustでのシリアライズ(データ構造をJSONなどの形式に変換)およびデシリアライズ(その逆の操作)に使用されます。
  2. Users構造体の定義:
    Users構造体は、ユーザー情報を表すためのデータ構造です。DeserializeSerializeトレイトが導出されており、これによりJSON形式との変換が可能になっています。serde(rename = "name")アトリビュートは、JSONキー名とRustフィールド名を対応させています。
  3. main関数(非同期):
    main関数は非同期であり、HTTPリクエストを受け取って処理します。この関数はResult<Response>を返します。
  4. ルーティング:
    HTTPエンドポイントごとに異なるハンドラ関数を定義しています。
    - GET /:id: 指定されたIDに対応するユーザーをデータベースから検索して返します。
    - GET /: すべてのユーザーをデータベースから取得して返します。
  5. データベース処理:
    SQLクエリを使って、D1データベース(Cloudflareのデータベースソリューション)からユーザーデータを取得しています。
  6. エラーハンドリング:
    データベースクエリやデータ取得の際にエラーが発生した場合、適切なHTTPステータスコード(404や500など)とエラーメッセージをレスポンスとして返します。

このコードは、RustでクラウドネイティブのWebアプリケーションを開発する際の一例を示しており、WebAssemblyとRustの組み合わせによる高性能かつセキュアなサーバレスアプリケーション開発を実現しています。

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?