このチュートリアルでは、workers-rs ↗ を使い、Rust から KV を直接読み書きする方法を学びます。
すべてのチュートリアルは、Cloudflare Workers アカウント、C3 ↗、および Wrangler のセットアップが完了している前提です。セットアップは Get started ガイド で行います。
このチュートリアルを完了するには、次のものが必要です。
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 ファイルを開き、ビルドコマンドの上に kv_namespaces のエントリを作ります。
{
"kv_namespaces": [
{
"binding": "cities",
"id": "e29b263ab50e42ce9b637fa8370175e8"
}
]
}[[kv_namespaces]]
binding = "cities"
id = "e29b263ab50e42ce9b637fa8370175e8"この設定により、Rust からバインディング "cities" で 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/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("Country not found", 404),
};
}
Response::error("Bad Request", 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("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