Skip to content

Adding support for Cloudflare Workers #65

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 11 commits into
base: main
Choose a base branch
from

Conversation

kpwebb
Copy link
Contributor

@kpwebb kpwebb commented Jun 30, 2025

Hi, as discussed on Discord, this pr adds Cloudflare Worker Rust support via their WASM bindings. Cloudflare's build tools compile workers into a WASM binary that's wrapped in a Javascript shim. To work in this environment I'm creating an optional CfWorkerServer that replaces the existing hyper HTTP endpoint and proxies Worker fetch requests into the existing Restate endpoint resolver.

One of the main challenges involves replacing bidi streams, which aren't supported in the Cloudflare Worker environment, with RequestResponse calls that move data across the WASM boundary. Most of what CfWorkerServer currently does is drain input and output streams into buffers that can be sent between the Restate core/handler and the JS request shim.

There might be ways to overcome this by using the JS API's ReadableStream directly. I'm exploring if Cloudflare's V8-based runtime environment supports this (in theory it should) but as an initial pass buffering the input and output streams should work as long as payload doesn't exhaust the container's 128MB memory limit.

In addition to adding the CfWorkerServer, I also added a with_protocol_mode() function to the Endpoint builder to enable optional support for the RequestResponse protocol mode as required by Cloudflare Workers

This is a WIP/request for discussion but I'm happy to make changes if you think this code should get merged into the SDK.

Here's an example service using CfWorkerServer in combination with the workers-rs crate:

use restate_sdk::prelude::*;

#[restate_sdk::service]
trait MyService {
    async fn my_handler() -> HandlerResult<()>;
}

struct MyServiceImpl;

impl MyService for MyServiceImpl {
    async fn my_handler(&self, _: Context<'_>) -> HandlerResult<()> {
        Ok(())
    }
}

#[worker::event(fetch)]
pub async fn main( req:worker::HttpRequest, _env: worker::Env, _ctx: worker::Context) -> worker::Result<http::Response<worker::Body>> {
    let endpoint = Endpoint::builder()
        .with_protocol_mode(restate_sdk::discovery::ProtocolMode::RequestResponse) // Cloudflare Workers don't support bidi streams
        .bind(MyServiceImpl.serve())
        .build();

    let cf_worker = CfWorkerServer::new(endpoint);

    return cf_worker.call(req).await;
}

This code needs to be compiled using wrangler with additional Rust compiler flags to enable wasm support for dependencies:

RUSTFLAGS='--cfg getrandom_backend="wasm_js"' npx wrangler dev

RUSTFLAGS='--cfg getrandom_backend="wasm_js"' npx wrangler deploy

I haven't found a way to build Rust workers via Cloudflare's CD build automation, as the rust compiler requires clang, which isn't currently installed and I wasn't able to find a way to add it at build time.

Copy link

github-actions bot commented Jun 30, 2025

All contributors have signed the CLA ✍️ ✅
Posted by the CLA Assistant Lite bot.

@kpwebb
Copy link
Contributor Author

kpwebb commented Jun 30, 2025

I have read the CLA Document and I hereby sign the CLA

@kpwebb
Copy link
Contributor Author

kpwebb commented Jun 30, 2025

fwiw, the cf_workers integration test works, but it has to be run via wasm-pack with the following command:

RUSTFLAGS='--cfg getrandom_backend="wasm_js"' wasm-pack test --node -- --no-default-features --features cf_workers --test cf_workers

@slinkydeveloper slinkydeveloper self-requested a review June 30, 2025 20:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant