Skip to content

Commit 3feb225

Browse files
committed
feat: Add support for DO websocket_auto_response.
Noticed this was missing from the rust apis. Basic bindgen, miniflare test, and sandbox example.
1 parent a16090a commit 3feb225

File tree

10 files changed

+109
-1
lines changed

10 files changed

+109
-1
lines changed

worker-sandbox/src/router.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,10 @@ pub fn make_router(data: SomeSharedData, env: Env) -> axum::Router {
224224
"/analytics-engine",
225225
get(handler!(analytics_engine::handle_analytics_event)),
226226
)
227+
.route(
228+
"/durable/auto-response",
229+
get(handler!(crate::test::auto_response::handle_auto_response)),
230+
)
227231
.fallback(get(handler!(catchall)))
228232
.layer(Extension(env))
229233
.layer(Extension(data))
@@ -364,6 +368,10 @@ pub fn make_router<'a>(data: SomeSharedData) -> Router<'a, SomeSharedData> {
364368
.delete_async("/r2/delete", handler!(r2::delete))
365369
.get_async("/socket/failed", handler!(socket::handle_socket_failed))
366370
.get_async("/socket/read", handler!(socket::handle_socket_read))
371+
.get_async(
372+
"/durable/auto-response",
373+
handler!(crate::test::auto_response::handle_auto_response),
374+
)
367375
.or_else_any_method_async("/*catchall", handler!(catchall))
368376
}
369377

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
use worker::*;
2+
3+
#[durable_object]
4+
pub struct AutoResponseObject {
5+
state: State,
6+
}
7+
8+
#[durable_object]
9+
impl DurableObject for AutoResponseObject {
10+
fn new(state: State, _env: Env) -> Self {
11+
Self { state }
12+
}
13+
14+
async fn fetch(&mut self, req: Request) -> Result<Response> {
15+
match req.path().as_str() {
16+
"/set" => {
17+
// Configure ping -> pong auto-response for all websockets bound to this DO.
18+
let pair = worker_sys::WebSocketRequestResponsePair::new("ping", "pong")?;
19+
self.state.set_websocket_auto_response(&pair);
20+
Response::ok("ok")
21+
}
22+
"/get" => {
23+
if let Some(pair) = self.state.get_websocket_auto_response() {
24+
let req_str = pair.request();
25+
let res_str = pair.response();
26+
Response::ok(format!("{req_str}:{res_str}"))
27+
} else {
28+
Response::ok("none")
29+
}
30+
}
31+
_ => Response::error("Not Found", 404),
32+
}
33+
}
34+
}
35+
36+
// Route handler to exercise the Durable Object from tests.
37+
#[worker::send]
38+
pub async fn handle_auto_response(
39+
_req: Request,
40+
env: Env,
41+
_data: crate::SomeSharedData,
42+
) -> Result<Response> {
43+
let namespace = env.durable_object("AUTO")?;
44+
let stub = namespace.id_from_name("singleton")?.get_stub()?;
45+
// Ensure auto-response is configured
46+
stub.fetch_with_str("https://fake-host/set").await?;
47+
// Retrieve and return it for assertion
48+
stub.fetch_with_str("https://fake-host/get").await
49+
}

worker-sandbox/src/test/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
pub mod auto_response;
12
pub mod durable;
23
pub mod export_durable_object;
34
pub mod put_raw;
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { describe, test, expect } from "vitest";
2+
import { mf } from "./mf";
3+
4+
describe("durable object websocket auto-response", () => {
5+
test("set and get auto-response pair", async () => {
6+
const resp = await mf.dispatchFetch("http://fake.host/durable/auto-response");
7+
const text = await resp.text();
8+
expect(text).toBe("ping:pong");
9+
});
10+
});

worker-sandbox/tests/mf.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ export const mf = new Miniflare({
5959
durableObjects: {
6060
COUNTER: "Counter",
6161
PUT_RAW_TEST_OBJECT: "PutRawTestObject",
62+
AUTO: "AutoResponseObject",
6263
},
6364
kvNamespaces: ["SOME_NAMESPACE", "FILE_SIZES", "TEST"],
6465
serviceBindings: {

worker-sandbox/wrangler.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ bindings = [
2929
{ name = "COUNTER", class_name = "Counter" },
3030
{ name = "ALARM", class_name = "AlarmObject" },
3131
{ name = "PUT_RAW_TEST_OBJECT", class_name = "PutRawTestObject" },
32+
{ name = "AUTO", class_name = "AutoResponseObject" },
3233
]
3334

3435
[[analytics_engine_datasets]]

worker-sys/src/types.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ mod socket;
1919
mod tls_client_auth;
2020
mod version;
2121
mod websocket_pair;
22+
mod websocket_request_response_pair;
2223

2324
pub use ai::*;
2425
pub use analytics_engine::*;
@@ -41,3 +42,4 @@ pub use socket::*;
4142
pub use tls_client_auth::*;
4243
pub use version::*;
4344
pub use websocket_pair::*;
45+
pub use websocket_request_response_pair::*;

worker-sys/src/types/durable_object/state.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use wasm_bindgen::prelude::*;
22

3-
use crate::types::{DurableObjectId, DurableObjectStorage};
3+
use crate::types::{DurableObjectId, DurableObjectStorage, WebSocketRequestResponsePair};
44

55
#[wasm_bindgen]
66
extern "C" {
@@ -43,4 +43,15 @@ extern "C" {
4343
this: &DurableObjectState,
4444
ws: &web_sys::WebSocket,
4545
) -> Result<Vec<String>, JsValue>;
46+
47+
#[wasm_bindgen(method, catch, js_name=setWebSocketAutoResponse)]
48+
pub fn set_websocket_auto_response(
49+
this: &DurableObjectState,
50+
pair: &WebSocketRequestResponsePair,
51+
) -> Result<(), JsValue>;
52+
53+
#[wasm_bindgen(method, catch, js_name=getWebSocketAutoResponse)]
54+
pub fn get_websocket_auto_response(
55+
this: &DurableObjectState,
56+
) -> Result<Option<WebSocketRequestResponsePair>, JsValue>;
4657
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
use wasm_bindgen::prelude::*;
2+
3+
#[wasm_bindgen]
4+
extern "C" {
5+
#[wasm_bindgen(extends=js_sys::Object)]
6+
#[derive(Debug, Clone, PartialEq, Eq)]
7+
pub type WebSocketRequestResponsePair;
8+
9+
#[wasm_bindgen(constructor, catch)]
10+
pub fn new(request: &str, response: &str) -> Result<WebSocketRequestResponsePair, JsValue>;
11+
12+
#[wasm_bindgen(method, getter)]
13+
pub fn request(this: &WebSocketRequestResponsePair) -> String;
14+
15+
#[wasm_bindgen(method, getter)]
16+
pub fn response(this: &WebSocketRequestResponsePair) -> String;
17+
}

worker/src/durable.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,14 @@ impl State {
264264
pub fn get_tags(&self, websocket: &WebSocket) -> Vec<String> {
265265
self.inner.get_tags(websocket.as_ref()).unwrap()
266266
}
267+
268+
pub fn set_websocket_auto_response(&self, pair: &worker_sys::WebSocketRequestResponsePair) {
269+
self.inner.set_websocket_auto_response(pair).unwrap();
270+
}
271+
272+
pub fn get_websocket_auto_response(&self) -> Option<worker_sys::WebSocketRequestResponsePair> {
273+
self.inner.get_websocket_auto_response().unwrap()
274+
}
267275
}
268276

269277
impl From<DurableObjectState> for State {

0 commit comments

Comments
 (0)