RustからWorkers KVを直接使用する
このチュートリアルでは、workers-rs ↗を使用して、RustからKVに直接読み書きする方法を学びます。
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.
このチュートリアルを完了するには、以下が必要です:
cargo install cargo-generateターミナルウィンドウを開き、次のコマンドを実行してRustのWorkerプロジェクトテンプレートを生成します:
cargo generate cloudflare/workers-rs次に、template/hello-world-httpテンプレートを選択し、プロジェクトに説明的な名前を付けてEnterを押します。新しいプロジェクトがディレクトリに作成されるはずです。プロジェクトをエディタで開き、npx wrangler devを実行してプロジェクトをコンパイルして実行します。
このチュートリアルでは、RustからWorkers KVを使用して、指定された国名によって都市を保存および取得するアプリを構築します。
ターミナルで、Wranglerを使用してcitiesのKVネームスペースを作成します。これにより、プロジェクトに追加するための設定が生成されます:
npx wrangler kv:namespace create citiesこの設定をプロジェクトに追加するには、wrangler.tomlファイルを開き、ビルドコマンドの上にkv_namespacesのエントリを作成します:
kv_namespaces = [ { binding = "cities", id = "e29b263ab50e42ce9b637fa8370175e8" }]
# ビルドコマンド...これで設定が完了したので、Rustからバインディング"cities"を使用して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リクエストを行います:
curl --json '{"city": "Paris"}' http://localhost:8787/FranceKVに保存された都市を取得するには、パスから国名を引き出し、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リクエストを行います:
curl http://localhost:8787/France完成したアプリのソースコードは以下を含むべきです:
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をデプロイするには、次のコマンドを実行します:
npx wrangler deploy