INTEGRITY Документация

Используйте Workers KV напрямую из Rust

Это руководство научит вас читать и записывать данные в KV напрямую из Rust с помощью workers-rs.

Прежде чем начать

Во всех руководствах предполагается, что вы уже выполнили Руководство по началу работы, который поможет вам настроить аккаунт Cloudflare Workers, C3, а также Wrangler.

Предварительные требования

Чтобы пройти это руководство, вам потребуется:

cargo install cargo-generate

1. Создайте проект 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/France

4. Прочитайте данные из 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/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