Introduction
Cloudflare Workersは、Cloudflareが提供するFaaSです。
GoogleのV8 JavaScriptエンジンを基盤として構築されたサーバーレスプラットフォームで、
高速な起動とエッジネットワークによる低遅延な処理が特徴です。
JavaScriptまたはWasmのコードを実行することができるので、
WebAssemblyにコンパイルできるなら他の言語でも実装可能です。
設定ファイルみたいなものを使いたい
アプリの設定などは通常、kv形式のプロパティファイル、
yamlやjsonなどのファイルを使います。
普通のアプリであればそれらのファイルをバンドルして実行時にloadすればよいのですが、
Workersである程度複雑な形式のデータをプロパティファイルとして扱いたい場合、
Cloudflare Workers KVやDurable Objects、
その他外部のストレージサービスなどからデータを取得しなければいけません。
いちいちそういったものを使うのが面倒なので、
今回はRust(workers-rs)を使って、
ローカルにあるJsonファイルのデータをWorkersからアクセスできるようにします。
Environment
- MacBook Pro (13-inch, M1, 2020)
- OS : MacOS 13.5.2
- Rust : 1.75.0
- Node : v20.8.1
Cloudflareのアカウントは設定済みとします。
Setup
まずはwranglerでプロジェクトを作成します。
% npx wrangler generate workers-example https://github.com/cloudflare/workers-sdk/templates/experimental/worker-rust
・・・
% cd workers-example
devコマンドでローカルで起動すればOKです。
% npm run dev
publishコマンドでリモート環境にデプロイされます。
% npm run publish
Try
Workersでプロパティにアクセスする方法はいくつかあるので、
それらについて紹介します。
varsを使う
シンプルにkv形式のプロパティを使いたいなら、wrangler.tomlで
varsセクションを使えばよいです。
[vars]
FOO = "bar"
Env経由でKeyを指定すれば値が取得できます。
use worker::*;
#[event(fetch)]
pub async fn main(mut req: Request, env: Env, _ctx: Context) -> Result<Response> {
let vars_value = env.var("FOO")?.to_string();
let response_body = format!("vars_value:{}",vars_value);
Response::ok(response_body)
}
secretを使う
パスワードやトークンなどの機密性が高いデータはsecretをつかいます。
# my_secretに値を設定
% npx wrangler secret put my_secret
use worker::*;
#[event(fetch)]
pub async fn main(mut req: Request, env: Env, _ctx: Context) -> Result<Response> {
let my_secret = env.secret("my_secret")?.to_string();
let response_body = format!("my_secret:{}",my_secret);
Response::ok(response_body)
}
ローカルで動かしたい場合、 .dev.varsファイルをルートに作成し、↓のように記述しておきます。
my_kmy_secretey=local_secret_value
Json形式のファイルを使う
シンプルなデータであればkey=value形式でよいのですが、
もう少し複雑なデータ形式を扱いたい場合もあります。
Cloudflare Workers KVを使えば複雑な形式のデータも扱えますが、
面倒なので、マクロをつかってそれっぽく使えるようにします。
まずはルートにexample.jsonファイルを作成します。
{
"key" : "bar",
"value":"buzz"
}
Cargo.tomlにcrateを追加します。
[dependencies]
once_cell = "1.19.0"
serde = "1.0.195"
serde_json = "1.0.111"
・・・
↑もしくはaddコマンドで追加。
% cargo add once_cell serde serde_json
Workersのコードです。
include_str!マクロでjsonファイルを展開し、
serdeでJSONオブジェクトに変換しています。
また、何度も処理が実行されないように
once_cellをつかっています。
use serde::{Deserialize, Serialize};
use worker::*;
use once_cell::sync::Lazy;
static CONFIG_JSON: Lazy<JsonData> = Lazy::new(|| {
let example_json_str = include_str!("../example.json");
serde_json::from_str(example_json_str).expect("JSON was not well-formatted")
});
#[derive(Serialize, Deserialize,Debug)]
struct JsonData {
key: String,
value: String,
}
#[event(fetch)]
pub async fn main(mut req: Request, env: Env, _ctx: Context) -> Result<Response> {
let config = &*CONFIG_JSON;
//console_log!("key:{}",config.key);
//console_log!("value:{}",config.value);
let response_body = format!("config:{:?}",config);
Response::ok(response_body)
}
include_str!マクロはコンパイル時にファイルの内容を
文字列リテラルとしてプログラムに埋め込みます。
そのため、当然ながらファイルの内容は実行時には変更できません。
また、JSONファイルが大きい場合はプログラムサイズも大きくなります。
serdeによるJSONのパースは実行時に行われるため、
不正なJSONである場合は実行時エラーになるので注意してください。
Summary
Cloudflare Workersでプロパティデータにアクセスする
いくつかの方法について紹介しました。
制限はありますが、簡単にJSONファイル内容にreadアクセスしたいなら
include_str!マクロを使うのが楽かと思います。