コンテンツにスキップ

RustからWorkers KVを直接使用する

Last reviewed: 4 months ago

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

Before you start

All of the tutorials assume you have already completed the Get started guide, which gets you set up with a Cloudflare Workers account, C3, and Wrangler.

前提条件

このチュートリアルを完了するには、以下が必要です:

  • Git
  • Wrangler CLI。
  • Rustツールチェーン。
  • そして、次のコマンドを実行してcargo-generateサブコマンドをインストールします:
Terminal window
cargo install cargo-generate

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

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

Terminal window
cargo generate cloudflare/workers-rs

次に、template/hello-world-httpテンプレートを選択し、プロジェクトに説明的な名前を付けてEnterを押します。新しいプロジェクトがディレクトリに作成されるはずです。プロジェクトをエディタで開き、npx wrangler devを実行してプロジェクトをコンパイルして実行します。

このチュートリアルでは、RustからWorkers KVを使用して、指定された国名によって都市を保存および取得するアプリを構築します。

2. KVネームスペースを作成する

ターミナルで、Wranglerを使用してcitiesのKVネームスペースを作成します。これにより、プロジェクトに追加するための設定が生成されます:

Terminal window
npx wrangler kv:namespace create cities

この設定をプロジェクトに追加するには、wrangler.tomlファイルを開き、ビルドコマンドの上にkv_namespacesのエントリを作成します:

kv_namespaces = [
{ binding = "cities", id = "e29b263ab50e42ce9b637fa8370175e8" }
]
# ビルドコマンド...

これで設定が完了したので、Rustからバインディング"cities"を使用してKVネームスペースにアクセスできます。

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

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

JSONを処理するために、プロジェクト依存関係としてSerdeをインストールします:cargo add serde。次に、src/lib.rsにアプリルーターとCountryの構造体を作成します:

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("不正なリクエスト", 400);
};
return match ctx.kv("cities")?.put(country, &city)?.execute().await {
Ok(_) => Response::ok(city),
Err(_) => Response::error("不正なリクエスト", 400),
};
})

ファイルを保存し、このエンドポイントをテストするためにPOSTリクエストを行います:

Terminal window
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("国が見つかりません", 404),
};
}
Response::error("不正なリクエスト", 400)
})

保存して、エンドポイントをテストするためにcurlリクエストを行います:

Terminal window
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("不正なリクエスト", 400);
};
return match ctx.kv("cities")?.put(country, &city)?.execute().await {
Ok(_) => Response::ok(city),
Err(_) => Response::error("不正なリクエスト", 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("国が見つかりません", 404),
};
}
Response::error("不正なリクエスト", 400)
})
.run(req, env)
.await
}

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

Terminal window
npx wrangler deploy

関連リソース