use worker::wasm_bindgen::JsCast; use worker::*; #[event(fetch)] async fn main(req: Request, _env: Env, _ctx: Context) -> Result { let url = req.url()?; let path = url.path(); match path { "/stream" => handle_stream().await, "/benchmark" => handle_benchmark(&url).await, _ => Response::error("Not Found", 404), } } /// Streams 1MB of data in chunks async fn handle_stream() -> Result { use futures_util::stream; // Create 1MB of data (1024 * 1024 bytes) let chunk_size = 8192; // 8KB chunks let num_chunks = (1024 * 1024) / chunk_size; // 128 chunks let chunk = vec![b'x'; chunk_size]; // Create a stream that yields the data let data_stream = stream::iter((0..num_chunks).map(move |_| Ok::, worker::Error>(chunk.clone()))); Response::from_stream(data_stream) } /// Main benchmark handler that makes 10 parallel sub-requests async fn handle_benchmark(url: &Url) -> Result { // Get the base URL from the request let base_url = format!( "{}://{}", url.scheme(), url.host_str().unwrap_or("localhost") ); let stream_url = format!("{base_url}/stream"); // Create 10 parallel sub-requests let mut tasks = Vec::new(); for i in 0..10 { let stream_url = stream_url.clone(); // Create a task for each sub-request let task = async move { // Make the sub-request to the streaming endpoint let mut response = Fetch::Url(stream_url.parse().unwrap()) .send() .await .map_err(|e| format!("Fetch error on request {i}: {e:?}"))?; // Consume the stream to ensure all data is read let body = response .bytes() .await .map_err(|e| format!("Body read error on request {i}: {e:?}"))?; let total_bytes = body.len() as u64; Ok::(total_bytes) }; tasks.push(task); } // Execute all tasks in parallel let performance = web_sys::js_sys::global() .unchecked_into::() .performance() .expect("performance API not available"); let start = performance.now(); let results = futures_util::future::join_all(tasks).await; let end = performance.now(); let duration_ms = (end - start) as u64; // Check for errors and sum up total bytes let mut total_bytes = 0u64; let mut errors = Vec::new(); for (i, result) in results.iter().enumerate() { match result { Ok(bytes) => total_bytes += bytes, Err(e) => errors.push(format!("Request {i}: {e}")), } } // Return summary as JSON let summary = serde_json::json!({ "success": errors.is_empty(), "duration_ms": duration_ms, "total_bytes": total_bytes, "num_requests": 10, "errors": errors, }); Response::from_json(&summary) }