概要
Cloudflare WorkersでRustがサポートされたようです。
Native Rust support on Cloudflare Workers
https://blog.cloudflare.com/workers-rust-sdk/
早速試してみました。
Cloudflareに登録
https://workers.cloudflare.com/ からSign upする。
:略:
お、dashboardのCreate a Workerのところに Rust
の文字が!
が、CLIでworkerを作成するので、このボタンは押さない。
API keyを取得する
「Edit Cloudflare Workers」の「Use template」ボタンを押す
細かい権限の設定ができるみたいだけど、用意されているままにして必須の項目をテキトーに入力してkeyを発行しました。
keyはメモっておく。
wrangler
というCLIのツールをインストールしてprojectを生成する
Cloudflare Workersを操作するCLIのツールらしいです。
https://github.com/cloudflare/wrangler
install
$ npm i @cloudflare/wrangler -g
version
$ wrangler -V
wrangler 1.19.2
API keyをセットする。
$ wrangler config
Enter API Token:と出るので、メモっておいたAPI keyを入力する。
こんな感じの出力で上手く設定できたっぽい。
💁 Validating credentials...
✨ Successfully configured. You can find your configuration file at: /home/mukai/.wrangler/config/default.toml
--type
にrustを指定してprojectを生成する。
$ wrangler generate --type=rust my-first-project
Creating project called `my-first-project`...
Done! New project created /home/mukai/my-first-project
⚠️ The template recommends the "javascript" type. Using type "rust" may cause errors, we recommend changing the type field in wrangler.toml to "javascript"
Rustの一式が生成された。
$ cd my-first-project
$ ls
CODE_OF_CONDUCT.md Cargo.lock Cargo.toml LICENSE_APACHE README.md src wrangler.toml
$
src/lib.srs
に main
があった。
ここにコードを書いていけばよさそう。
自動生成されたコードはこうなっていた。
use serde_json::json;
use worker::*;
mod utils;
fn log_request(req: &Request) {
console_log!(
"{} - [{}], located at: {:?}, within: {}",
Date::now().to_string(),
req.path(),
req.cf().coordinates().unwrap_or_default(),
req.cf().region().unwrap_or("unknown region".into())
);
}
#[event(fetch)]
pub async fn main(req: Request, env: Env) -> Result<Response> {
log_request(&req);
// Optionally, get more helpful error messages written to the console in the case of a panic.
utils::set_panic_hook();
// Optionally, use the Router to handle matching endpoints, use ":name" placeholders, or "*name"
// catch-alls to match on specific patterns. The Router takes some data with its `new` method
// that can be shared throughout all routes. If you don't need any shared data, use `()`.
let router = Router::new(());
// Add as many routes as your Worker needs! Each route will get a `Request` for handling HTTP
// functionality and a `RouteContext` which you can use to and get route parameters and
// Enviornment bindings like KV Stores, Durable Objects, Secrets, and Variables.
router
.post_async("/form/:field", |mut req, ctx| async move {
if let Some(name) = ctx.param("field") {
let form = req.form_data().await?;
match form.get(name) {
Some(FormEntry::Field(value)) => {
return Response::from_json(&json!({ name: value }))
}
Some(FormEntry::File(_)) => {
return Response::error("`field` param in form shouldn't be a File", 422);
}
None => return Response::error("Bad Request", 400),
}
}
Response::error("Bad Request", 400)
})
.get("/worker-version", |_, ctx| {
let version = ctx.var("WORKERS_RS_VERSION")?.to_string();
Response::ok(version)
})
.run(req, env)
.await
}
buildする
とりあえず生成されたコードには何も手を加えずにdeployまでしたい。
buildして
$ wrangler build
🌀 Running cargo install -q worker-build && worker-build --release
Installing wasm-pack...
Updating crates.io index
Downloaded wasm-pack v0.10.1
Downloaded 1 crate (420.1 KB) in 0.67s
Installing wasm-pack v0.10.1
Downloaded human-panic v1.0.3
:略:
Compiling quote v1.0.9
error: failed to compile `wasm-pack v0.10.1`, intermediate artifacts can be found at `/tmp/cargo-installz3WVFF`
Caused by:
failed to run custom build command for `openssl-sys v0.9.66`
Caused by:
process didn't exit successfully: `/tmp/cargo-installz3WVFF/release/build/openssl-sys-38fd3389ac96e4ad/build-script-main` (exit status: 101)
--- stdout
cargo:rustc-cfg=const_fn
cargo:rerun-if-env-changed=X86_64_UNKNOWN_LINUX_GNU_OPENSSL_NO_VENDOR
X86_64_UNKNOWN_LINUX_GNU_OPENSSL_NO_VENDOR unset
cargo:rerun-if-env-changed=OPENSSL_NO_VENDOR
OPENSSL_NO_VENDOR unset
CC_x86_64-unknown-linux-gnu = None
CC_x86_64_unknown_linux_gnu = None
HOST_CC = None
CC = None
CFLAGS_x86_64-unknown-linux-gnu = None
CFLAGS_x86_64_unknown_linux_gnu = None
HOST_CFLAGS = None
CFLAGS = None
CRATE_CC_NO_DEFAULTS = None
DEBUG = Some("false")
CARGO_CFG_TARGET_FEATURE = Some("fxsr,sse,sse2")
running "perl" "./Configure" "--prefix=/tmp/cargo-installz3WVFF/release/build/openssl-sys-abc3acc08e9a4eff/out/openssl-build/install" "no-dso" "no-shared" "no-ssl3" "no-unit-test" "no-comp" "no-zlib" "no-zlib-dynamic" "no-md2" "no-rc5" "no-weak-ssl-ciphers" "no-camellia" "no-idea" "no-seed" "linux-x86_64" "-O2" "-ffunction-sections" "-fdata-sections" "-fPIC" "-m64"
Configuring OpenSSL version 1.1.1l (0x101010cfL) for linux-x86_64
Using os-specific seed configuration
Creating configdata.pm
Creating Makefile
**********************************************************************
*** ***
*** OpenSSL has been successfully configured ***
*** ***
*** If you encounter a problem while building, please open an ***
*** issue on GitHub <https://github.com/openssl/openssl/issues> ***
*** and include the output from the following command: ***
*** ***
*** perl configdata.pm --dump ***
*** ***
*** (If you are new to OpenSSL, you might want to consult the ***
*** 'Troubleshooting' section in the INSTALL file first) ***
*** ***
**********************************************************************
running "make" "depend"
--- stderr
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Os { code: 2, kind: NotFound, message: "No such file or directory" }', /home/mukai/.cargo/registry/src/github.com-1ecc6299db9ec823/openssl-src-111.16.0+1.1.1l/src/lib.rs:477:39
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Error: installation of wasm-pack exited with status exit status: 101
Error: Build failed! Status Code: 1
$
こけよる
エラーメッセージでググったところ、Ubuntuでは build-essential
を入れたら解決したという情報が
https://zenn.dev/dozo/articles/ed2e846847af5d
CentOSだったのでDevelopment Toolsを入れてみる。
$ sudo yum groupinstall 'Development Tools'
私の環境では openssl-devel
が既にインストールされていましたが、多分これも必要ですね。
(https://github.com/cloudflare/workers-rs に依存パッケージの説明などがありません)
依存パッケージが揃っていればbuildに成功した。
$ wrangler build
🌀 Running cargo install -q worker-build && worker-build --release
Installing wasm-pack...
Updating crates.io index
Installing wasm-pack v0.10.1
:略:
Compiling my-first-project v0.1.0 (/home/mukai/my-first-project)
Finished release [optimized] target(s) in 2m 07s
[INFO]: Installing wasm-bindgen...
[INFO]: Optimizing wasm binaries with `wasm-opt`...
[INFO]: Optional fields missing from Cargo.toml: 'description', 'repository', and 'license'. These are not necessary, but recommended
[INFO]: :-) Done in 2m 15s
[INFO]: :-) Your wasm pkg is ready to publish at /home/mukai/my-first-project/build.
✨ Build completed successfully!
手元で動かすコマンドはこう
$ wrangler dev
🌀 Running cargo install -q worker-build && worker-build --release
[INFO]: Checking for the Wasm target...
[INFO]: Compiling to Wasm...
Finished release [optimized] target(s) in 0.05s
[INFO]: Installing wasm-bindgen...
[INFO]: Optimizing wasm binaries with `wasm-opt`...
[INFO]: Optional fields missing from Cargo.toml: 'description', 'repository', and 'license'. These are not necessary, but recommended
[INFO]: :-) Done in 2.25s
[INFO]: :-) Your wasm pkg is ready to publish at /home/mukai/my-first-project/build.
👂 Listening on http://127.0.0.1:8787
curlで叩けるよ。
$ curl "http://127.0.0.1:8787/worker-version"
0.0.4
deploy
$ wrangler publish
🌀 Running cargo install -q worker-build && worker-build --release
[INFO]: Checking for the Wasm target...
[INFO]: Compiling to Wasm...
Finished release [optimized] target(s) in 0.05s
[INFO]: Installing wasm-bindgen...
[INFO]: Optimizing wasm binaries with `wasm-opt`...
[INFO]: Optional fields missing from Cargo.toml: 'description', 'repository', and 'license'. These are not necessary, but recommended
[INFO]: :-) Done in 2.26s
[INFO]: :-) Your wasm pkg is ready to publish at /home/mukai/my-first-project/build.
✨ Build completed successfully!
✨ Successfully published your script to
https://my-first-project.muk-ai.workers.dev
これでもう動いているので、ブラウザで開けば表示できた。
https://my-first-project.muk-ai.workers.dev/worker-version
/form/:field
はPOSTしたデータをjsonで返してくるので動的なページであることがわかる。
$ curl -X POST "https://my-first-project.muk-ai.workers.dev/form/hoge" -F 'hoge=this is post data'
{"hoge":"this is post data"}
dashboardにdeployしたプロジェクトが表示された。
dashboardでは処理したリクエストの回数などが確認できる。
10万req/dayまで無料です。
あと無料プランだと処理の実行時間は10msというリミットがあるようです。
感想
え? wasmをJavaScriptから呼び出さなくていいのめちゃくちゃ良いですね