Skip to content

非公式本サイトは非公式の日本語ドキュメントであり、Cloudflare 公式サイトではありません。最新情報はdevelopers.cloudflare.comをご確認ください。

Rust から Workers KV を直接使う

最終更新 Markdown で表示Agent セットアップ

このチュートリアルでは、workers-rs を使い、Rust から KV を直接読み書きする方法を学びます。

始める前に

すべてのチュートリアルは、Cloudflare Workers アカウント、C3、および Wrangler のセットアップが完了している前提です。セットアップは Get started ガイド で行います。

前提条件

このチュートリアルを完了するには、次のものが必要です。

  • Git
  • Wrangler CLI
  • Rust ツールチェーン
  • 次のコマンドで入れる cargo-generate サブコマンド:
cargo install cargo-generate

1. Rust で Worker プロジェクトを作る

ターミナルを開き、次のコマンドを実行して、Rust の Worker プロジェクトテンプレートを生成します。

cargo generate cloudflare/workers-rs

次に template/hello-world-http テンプレートを選び、分かりやすいプロジェクト名を付けて Enter を押します。ディレクトリに新しいプロジェクトが作られます。エディターでプロジェクトを開き、npx wrangler dev を実行してコンパイルと実行をします。

このチュートリアルでは、Rust から Workers KV を使い、国名を指定して都市を保存・取得するアプリを作ります。

2. KV 名前空間を作る

ターミナルで Wrangler を使い、cities 用の KV 名前空間を作ります。プロジェクトに追加する設定が生成されます。

npx wrangler kv namespace create cities

この設定をプロジェクトに追加するには、Wrangler ファイルを開き、ビルドコマンドの上に kv_namespaces のエントリを作ります。

{
	"kv_namespaces": [
		{
			"binding": "cities",
			"id": "e29b263ab50e42ce9b637fa8370175e8"
		}
	]
}
[[kv_namespaces]]
binding = "cities"
id = "e29b263ab50e42ce9b637fa8370175e8"

この設定により、Rust からバインディング "cities" で KV 名前空間にアクセスできます。

3. KV にデータを書き込む

このアプリでは 2 つのルートを作ります。都市を受け取って KV に保存する POST ルートと、指定した国の都市を取得する GET ルートです。たとえば、/France への POST リクエストでボディが {"city": "Paris"} なら、フランスの都市として Paris のエントリを作ります。/France への GET リクエストは KV から取得し、Paris を返します。

JSON を扱うため、プロジェクト依存関係として Serde を入れます(cargo add serde)。次に src/lib.rs でアプリのルーターと Country の struct を作ります。

use serde::{Deserialize, Serialize};
use worker::*;

#[event(fetch)]
async fn fetch(req: Request, env: Env, _ctx: Context) -> Result<Response> {
    let router = Router::new();

    #[derive(Serialize, Deserialize, Debug)]
    struct Country {
        city: String,
    }

    router
        // TODO:
        .post_async("/:country", |_, _| async move { Response::empty() })
        // TODO:
        .get_async("/:country", |_, _| async move { Response::empty() })
        .run(req, env)
        .await
}

POST ハンドラーでは、パスから国名を、リクエストボディから都市名を取得します。国をキー、都市を値として KV に保存します。最後に、アプリは都市名を返します。

.post_async("/:country", |mut req, ctx| async move {
    let country = ctx.param("country").unwrap();
    let city = match req.json::<Country>().await {
        Ok(c) => c.city,
        Err(_) => String::from(""),
    };
    if city.is_empty() {
        return Response::error("Bad Request", 400);
    };
    return match ctx.kv("cities")?.put(country, &city)?.execute().await {
        Ok(_) => Response::ok(city),
        Err(_) => Response::error("Bad Request", 400),
    };
})

ファイルを保存し、このエンドポイントをテストする POST リクエストを送ります。

curl --json '{"city": "Paris"}' http://localhost:8787/France

4. KV からデータを読み取る

KV に保存した都市を取得するには、パスから国名を取り出し、KV を検索する GET ルートを書きます。国が見つからない場合のエラー処理も必要です。

.get_async("/:country", |_req, ctx| async move {
    if let Some(country) = ctx.param("country") {
        return match ctx.kv("cities")?.get(country).text().await? {
            Some(city) => Response::ok(city),
            None => Response::error("Country not found", 404),
        };
    }
    Response::error("Bad Request", 400)
})

保存し、エンドポイントをテストする curl リクエストを送ります。

curl http://localhost:8787/France

5. プロジェクトをデプロイする

完成したアプリのソースコードには、次が含まれます。

use serde::{Deserialize, Serialize};
use worker::*;

#[event(fetch)]
async fn fetch(req: Request, env: Env, _ctx: Context) -> Result<Response> {
    let router = Router::new();

    #[derive(Serialize, Deserialize, Debug)]
    struct Country {
        city: String,
    }

    router
        .post_async("/:country", |mut req, ctx| async move {
            let country = ctx.param("country").unwrap();
            let city = match req.json::<Country>().await {
                Ok(c) => c.city,
                Err(_) => String::from(""),
            };
            if city.is_empty() {
                return Response::error("Bad Request", 400);
            };
            return match ctx.kv("cities")?.put(country, &city)?.execute().await {
                Ok(_) => Response::ok(city),
                Err(_) => Response::error("Bad Request", 400),
            };
        })
        .get_async("/:country", |_req, ctx| async move {
            if let Some(country) = ctx.param("country") {
                return match ctx.kv("cities")?.get(country).text().await? {
                    Some(city) => Response::ok(city),
                    None => Response::error("Country not found", 404),
                };
            }
            Response::error("Bad Request", 400)
        })
        .run(req, env)
        .await
}

Worker をデプロイするには、次のコマンドを実行します。

npx wrangler deploy

関連リソース

役に立ちましたか?