13
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Cloudflare WorkersでRustがサポートされた

Posted at

概要

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 の文字が!:eyes:

image.png

が、CLIでworkerを作成するので、このボタンは押さない。

API keyを取得する

「Create Token」ボタンを押す
image.png

「Edit Cloudflare Workers」の「Use template」ボタンを押す
image.png

細かい権限の設定ができるみたいだけど、用意されているままにして必須の項目をテキトーに入力して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.srsmain があった。
ここにコードを書いていけばよさそう。
自動生成されたコードはこうなっていた。

src/lib.rs
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
$

こけよる:sob:
エラーメッセージでググったところ、Ubuntuでは build-essential を入れたら解決したという情報が:pray:
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したプロジェクトが表示された。

image.png

dashboardでは処理したリクエストの回数などが確認できる。
10万req/dayまで無料です。

image.png

あと無料プランだと処理の実行時間は10msというリミットがあるようです。
image.png

感想

え? wasmをJavaScriptから呼び出さなくていいのめちゃくちゃ良いですね

13
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?