[Rust] Cloudflare Workersで画像の加工をやってみる
Introduction
最近各所で話題のCloudflare。
Wranglerも2.0になり、worker-rustの
テンプレも動いたので、それを少し変更して画像の加工処理を実装したいと思います。
Cloudflare Workers?
Cloudflare Workersは、Cloudflare上で実行される
サーバーレスアプリケーションの実行環境です。
AWSで近いサービスを挙げると、AWS Lambda(Lambda@Edge)になるかと思います。
自動スケーリング&Edgeロケーション&コールドスタートなしで起動する、
などの特徴があり、対応言語はJS, Rust, C, C++です。
また、WorkersKV(低レイテンシのKey-Valueデータストア)を使うことで
(SSRやったりとか)Workersの用途が広がります。
Environment
環境は以下。
- MacBook Pro (13-inch, M1, 2020)
- OS : MacOS 11.3.1
- rust : 1.60.0
Try
今回は、Cloudflare WorkersとRust(workers-rs)を使って
画像のグレースケール処理を実装してみます。
ローカルから画像ファイルをおくるとグレースケールした画像を返します。
CloudflareアカウントやWranglerについてはここにある通り設定して、
worker-rustでgenerateした雛形を使用します。
では実装してみましょう。
依存ライブラリの追加
画像のグレースケール処理をするためにimage crateを使います。
Cargo.tomlのdependenciesに追記。
[dependencies] cfg-if = "0.1.2" worker = "0.0.9" image = "*"
処理の追加
main.rsに/fileリクエスト時の処理を記述します。
ファイルデータをPOSTすると画像を加工して返します。
・・・・・ router .get("/", |_, _| Response::ok("Hello from Workers!")) .post_async("/file",|mut req,_ctx| async move { console_log!("/file request."); if let Some(file) = req.form_data().await?.get("upfile") { return match file { FormEntry::File(image_buf) => { let gray_image_buf = grayscale(&(image_buf.bytes().await?)); let response = Response::from_bytes(gray_image_buf)?; let mut headers = Headers::new(); headers.set("content-type","image/png")?; Ok(response.with_headers(headers)) } _ => Response::error("`file` part of POST form must be a file", 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 ・・・・・
grayscale関数の中身です。
ファイルデータのbyte配列をimage crateでグレースケールしています。
fn grayscale(image_buf:&Vec<u8>) -> Vec<u8>{ let base_image = image::load_from_memory(image_buf).expect("error load_from_memory!"); let gray = base_image.into_luma8(); let mut result_buf: Vec<u8> = Vec::new(); gray.write_to(&mut Cursor::new(&mut result_buf), image::ImageOutputFormat::Png).expect("io error"); result_buf }
動作確認
wrangler devコマンドを実行してローカルで起動します。
% wrangler dev ⛅️ wrangler 2.0.6 ------------------- Running custom build: 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.13s [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 3.66s [INFO]: ? Your wasm pkg is ready to publish at /path/your/rust-example/build. ⬣ Listening at http://localhost:8787
適当な画像を用意して、curlで/fileに対してPOSTします。
グレースケール処理が実行され、--outputで指定したファイル名でダウンロードされます。
curl -X POST -F upfile=@/path/your/sample.jpg http://localhost:8787/file --output ./gray-sample.png % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 578k 100 442k 100 136k 758k 234k --:--:-- --:--:-- --:--:-- 992k
Cloudflareにpublish
ローカルで動作確認できたらデプロイしてみます。
% wrangler publish --name <Project Name> ⛅️ wrangler 2.0.6 ------------------- Running custom build: 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.18s [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 3.81s [INFO]: ? Your wasm pkg is ready to publish at /path/your/rust-example/build. Uploaded rust-example (2.22 sec) Published rust-example (0.33 sec) <Project Name>.<sub domain>.workers.dev
デプロイが成功してURLも表示されました。
こちらに対しても同じようにアクセスしてみます。
% curl -X POST -F upfile=@/path/your/sample.jpg http://<Project Name>.<sub domain>.workers.dev/file --output ./cf-gray-sample.png % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 3489k 100 856k 100 2632k 349k 1073k 0:00:02 0:00:02 --:--:-- 1423k
問題なくアクセスできました。
雛形作成からローカルでの動作確認、デプロイまで簡単です。
Workers&RemixとかCloudflare Workers KVとかもおもしろそうなので、
興味のあるかたはご確認ください。