← Cloudflare Workers / workers / tutorials
Используйте Workers KV напрямую из Rust
Это руководство научит вас читать и записывать данные в KV напрямую из Rust с помощью workers-rs ↗.
Прежде чем начать
Во всех руководствах предполагается, что вы уже выполнили Руководство по началу работы, который поможет вам настроить аккаунт Cloudflare Workers, C3 ↗, а также Wrangler.
Предварительные требования
Чтобы пройти это руководство, вам потребуется:
cargo install cargo-generate1. Создайте проект Worker на Rust
Откройте окно терминала и выполните следующую команду, чтобы сгенерировать шаблон проекта Worker на Rust:
cargo generate cloudflare/workers-rsЗатем выберите template/hello-world-http шаблон, дайте проекту понятное имя и нажмите Enter. В вашем каталоге будет создан новый проект. Откройте проект в редакторе и выполните npx wrangler dev чтобы скомпилировать и запустить ваш проект.
В этом руководстве вы будете использовать Workers KV из Rust, чтобы создать приложение для сохранения и получения городов по названию страны.
2. Создание пространства имён KV
В терминале используйте Wrangler, чтобы создать пространство имён KV для cities. Это создаёт конфигурацию, которую нужно добавить в проект:
npx wrangler kv namespace create citiesЧтобы добавить эту конфигурацию в проект, откройте файл Wrangler и создайте запись для kv_namespaces над командой сборки:
{
"kv_namespaces": [
{
"binding": "cities",
"id": "e29b263ab50e42ce9b637fa8370175e8"
}
]
}[[kv_namespaces]]
binding = "cities"
id = "e29b263ab50e42ce9b637fa8370175e8"После этой настройки можно обращаться к KV namespace через binding "cities" из Rust.
3. Запись данных в KV
В этом приложении вы создадите два маршрута: POST маршрут для получения и сохранения города в KV, а также GET маршрут для получения города заданной страны. Например, POST запрос к /France с телом {"city": "Paris"} должен создать запись о Париже как городе во Франции. GET запрос к /France должен получить значение из KV и ответить Paris.
Установка Serde ↗ как зависимость проекта для обработки JSON cargo add serde. Затем создайте маршрутизатор приложения и структуру для Country в src/lib.rs:
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/France4. Прочитайте данные из KV
Чтобы получить города, сохранённые в KV, напишите GET маршрут, который извлекает название страны из пути и выполняет поиск в KV. Также нужна обработка ошибок на случай, если страна не найдена:
.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/France5. Разверните проект
Исходный код готового приложения должен включать следующее:
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