百科.dev
全部条目AI 编程趋势榜开源项目技术资讯提交条目
登录
< 返回工具列表
W

workers-rs

> 编程语言
开源

通过 WebAssembly 将 Cloudflare 工人写入 100% 的 Rust

3.6K stars0 点赞0 次浏览
访问官网GitHub

工具介绍

通过 WebAssembly 将 Cloudflare 工人写入 100% 的 Rust

Ergonomic Rust bindings to Cloudflare Workers environment. Write your entire worker in Rust!

Read the Notes and FAQ

Example Usage

…

Getting Started

The project uses wrangler for running and publishing your Worker.

Use cargo generate to start from a template:

cargo generate cloudflare/workers-rs

There are several templates to choose from. During generation you will be prompted to enable panic=unwind and abort recovery (see Panic Recovery below). You should see a new project layout with a src/lib.rs. Start there! Use any local or remote crates and modules (as long as they compile to the wasm32-unknown-unknown target).

Once you're ready to run your project, run your worker locally:

npx wrangler dev

Finally, go live:

# configure your routes, zones & more in your worker's `wrangler.toml` file
npx wrangler deploy

If you would like to have wrangler installed on your machine, see instructions in wrangler repository.

http Feature

worker 0.0.21 introduced an http feature flag which starts to replace custom types with widely used types from the http crate.

This makes it much easier to use crates which use these standard types such as axum and hyper.

This currently does a few things:

  1. Introduce Body, which implements http_body::Body and is a simple wrapper around web_sys::ReadableStream.
  2. The req argument when using the [event(fetch)] macro becomes http::Request<worker::Body>.
  3. The expected return type for the fetch handler is http::Response<B> where B can be any http_body::Body<Data=Bytes>.
  4. The argument for Fetcher::fetch_request is http::Request<worker::Body>.
  5. The return type of Fetcher::fetch_request is Result<http::Response<worker::Body>>.

The end result is being able to use frameworks like axum directly (see example):

pub async fn root() -> &'static str {
    "Hello Axum!"
}

fn router() -> Router {
    Router::new().route("/", get(root))
}

#[event(fetch)]
async fn fetch(
    req: HttpRequest,
    _env: Env,
    _ctx: Context,
) -> Result<http::Response<axum::body::Body>> {
    Ok(router().call(req).await?)
}

We also implement try_from between worker::Request and http::Request<worker::Body>, and between worker::Response and http::Response<worker::Body>. This allows you to convert your code incrementally if it is tightly coupled to the original types.

Or use the Router:

Parameterize routes and access the parameter values from within a handler. Each handler function takes a Request, and a RouteContext. The RouteContext has shared data, route params, Env bindings, and more.

…

Durable Object, KV, Secret, & Variable Bindings

All "bindings" to your script (Durable Object & KV Namespaces, Secrets, Variables and Version) are accessible from the env parameter provided to both the entrypoint (main in this example), and to the route handler callback (in the ctx argument), if you use the Router from the worker crate.

…

For more information about how to configure these bindings, see:

  • https://developers.cloudflare.com/workers/cli-wrangler/configuration#keys
  • https://developers.cloudflare.com/workers/learning/using-durable-objects#configuring-durable-object-bindings
  • https://developers.cloudflare.com/workers/runtime-apis/bindings/version-metadata/

Durable Objects

Define a Durable Object in Rust

To define a Durable Object using the worker crate you need to implement the DurableObject trait on your own struct. Additionally, the #[durable_object] attribute macro must be applied to the struct definition.

…

You'll need to "migrate" your worker script when it's published so that it is aware of this new Durable Object, and include a binding in your wrangler.toml.

  • Include the Durable Object binding type in you wrangler.toml file:
# ...

[durable_objects]
bindings = [
  { name = "CHATROOM", class_name = "Chatroom" } # the `class_name` uses the Rust struct identifier name
]

[[migrations]]
tag = "v1" # Should be unique for each entry
new_classes = ["Chatroom"] # Array of new classes

SQLite Storage in Durable Objects

Durable Objects can use SQLite for persistent storage, providing a relational database interface. To enable SQLite storage, you need to use new_sqlite_classes in your migration and access the SQL storage through state.storage().sql().

…

Configure your wrangler.toml to enable SQLite storage:

# ...

[durable_objects]
bindings = [
  { name = "SQL_COUNTER", class_name = "SqlCounter" }
]

[[migrations]]
tag = "v1" # Should be unique for each entry
new_sqlite_classes = ["SqlCounter"] # Use new_sqlite_classes for SQLite-enabled objects
  • For more information about migrating your Durable Object as it changes, see the docs here: https://developers.cloudflare.com/workers/learning/using-durable-objects#durable-object-migrations-in-wranglertoml

Queues

Enabling queues

As queues are in beta you need to enable the queue feature flag.

Enable it by adding it to the worker dependency in your Cargo.toml:

worker = {version = "...", features = ["queue"]}

Example worker consuming and producing messages:

…

You'll need to ensure you have the correct bindings in your wrangler.toml:

# ...
[[queues.consumers]]
queue = "myqueueotherqueue"
max_batch_size = 10
max_batch_timeout = 30

[[queues.producers]]
queue = "myqueue"
binding = "my_queue"

RPC Support

workers-rs has experimental support for Workers RPC. For now, this relies on JavaScript bindings and may require some manual usage of wasm-bindgen.

Not all features of RPC are supported yet (or have not been tested), including:

  • Function arguments and return values
  • Class instances
  • Stub forwarding

RPC Server

Writing an RPC server with workers-rs is relatively simple. Simply export methods using wasm-bindgen. These will be automatically detected by worker-build and made available to other Workers. See example.

RPC Client

Creating types and bindings for invoking another Worker's RPC methods is a bit more involved. You will need to write more complex wasm-bindgen bindings and some boilerplate to make interacting with the RPC methods more idiomatic. See example.

With manually written bindings, it should be possible to support non-primitive argument and return types, using serde-wasm-bindgen.

Generating Client Bindings

There are many routes that can be taken to describe RPC interfaces. Under the hood, Workers RPC uses Cap'N Proto. A possible future direction is for Wasm guests to include Cap'N Proto serde support and speak directly to the RPC protocol, bypassing JavaScript. This would likely involve defining the RPC interface in Cap'N Proto schema and generating Rust code from that.

Another popular interface schema in the WebAssembly community is WIT. This is a lightweight format designed for the WebAssembly Component model. workers-rs includes an experimental code generator which allows you to describe your RPC interface using WIT and generate JavaScript bindings as shown in the rpc-client example. The easiest way to use this code generator is using a build script as shown in the example. This code generator is pre-alpha, with no support guarantee, and implemented only for primitive types at this time.

CPU Limits

Rust Workers have CPU limits assigned by the platform. To gracefully detect these limits we provide a worker::signals API.

This allows for graceful backoff by detecting when the Worker is near its CPU limit and will be terminated using:

use worker::signals;

pub fn do_work () {
    while !signals::is_near_cpu_limit() {
        // hot loop
    }
}

See Signal Example for a full end-to-end workflow.

Panic Recovery with --panic-unwind

By default, Rust panics in Workers compile with panic=abort, which terminates the WebAssembly instance. The --panic-unwind flag for worker-build changes this behavior so that panics are caught and converted to JavaScript exceptions, allowing the Worker to continue serving requests after a panic.

When running worker-build directly:

worker-build --panic-unwind

Example wrangler.toml build command:

[build]
command = "cargo install worker-build && worker-build --release --panic-unwind"

This flag:

  • Uses the nightly Rust toolchain (installed automatically if missing)
  • Rebuilds std with -Zbuild-std=std,panic_unwind and -Cpanic=unwind (the rust-src component and wasm32-unknown-unknown target for nightly are installed automatically if missing)
  • Enables wasm-bindgen's panic catching support, which catches panics at FFI boundaries and converts them to JavaScript PanicError exceptions
  • Registers schedule_reinit() via wasm-bindgen's abort handling hooks to automatically recover from critical errors (e.g. unreachable, stack overflow, or out-of-memory). After a hard abort the WebAssembly instance is transparently reinitialized on the next request, with an internal instance ID bump so that Durable Object instances are recreated.

Without this flag, any panic will terminate the isolate. With it, individual requests that trigger a panic will fail with an error response while subsequent requests continue to work normally.

Unwind Safety

When building with panic=unwind, exported function arguments and closure captures must satisfy Rust's UnwindSafe trait. The worker crate macros wrap handler callbacks with AssertUnwindSafe automatically, but if you pass closures to JavaScript via Closure::new or similar APIs you may need to wrap non-unwind-safe captures (e.g. &mut T, Cell<T>, RefCell<T>) in std::panic::AssertUnwindSafe:

use std::cell::Cell;
use std::panic::AssertUnwindSafe;
use wasm_bindgen::prelude::*;

let counter = Cell::new(0u32);
let counter_ref = AssertUnwindSafe(&counter);
let closure = Closure::new(move || {
    counter_ref.set(counter_ref.get() + 1);
});

Alternatively, Closure::own_aborting and other *_aborting variants skip the UnwindSafe requirement but will abort on panic instead of catching it. See the wasm-bindgen closures documentation for the full set of closure APIs and their unwind behavior.

Testing with Miniflare

In order to test your Rust worker locally, the best approach is to use Miniflare. However, because Miniflare is a Node package, you will need to write your end-to-end tests in JavaScript or TypeScript in your project. The official documentation for writing tests using Miniflare is available here. This documentation being focused on JavaScript / TypeScript codebase, you will need to configure as follows to make it work with your Rust-based, WASM-generated worker:

Step 1: Add Wrangler and Miniflare to your devDependencies

npm install --save-dev wrangler miniflare

Step 2: Build your worker before running the tests

Make s

GitHub Issues· 181 开放

在 GitHub 查看全部
  • #1057

    [Feature] Support reading queue message attempts field

    更新于 2026年9月16日
  • #1050

    [BUG] ai.run misbehaves with serde_json::Value, should probably use json_compatible serializer

    更新于 2026年9月14日
  • #1052

    [Feature] support .raw({columnNames: true}) for D1PreparedStatement

    更新于 2026年9月1日
  • #1051

    [Feature] Honor exact http_body::Body::size_hint via FixedLengthStream

    更新于 2026年8月30日
  • #1013

    [BUG] Queue: typed `MessageBatch<T>` deserialize via `serde_wasm_bindgen::from_value` mangles payloads — offer a JSON-based path

    更新于 2026年8月20日

核心特点

  • •https://developers.cloudflare.com/workers/cli-wrangler/configuration#keys
  • •https://developers.cloudflare.com/workers/learning/using-durable-objects#configuring-durable-object-bindings
  • •https://developers.cloudflare.com/workers/runtime-apis/bindings/version-metadata/
  • •Include the Durable Object binding type in you wrangler.toml file:
  • •For more information about migrating your Durable Object as it changes, see the docs here:
  • •Function arguments and return values
  • •Class instances
  • •Stub forwarding
  • •Uses the nightly Rust toolchain (installed automatically if missing)
  • •Rebuilds std with -Zbuild-std=std,panic_unwind and -Cpanic=unwind (the rust-src component and wasm32-unknown-unknown target for nightly are installed automatically if missing)

> 标签

Rustcloudflareffirustserverless

暂无评论,来聊聊你的看法吧

> 工具信息

发布日期2026年8月1日
最后更新2026年9月17日
分类编程语言
定价开源

> 相关工具

T
TypeScript
JavaScript 的超集,为前端与全栈提供静态类型
P
Python
通用编程语言,广泛用于 Web、数据与 AI
G
Go
Google 推出的简洁高效系统语言