//! `web_client` — the client delivery layer. It owns *how* the embedded //! [`web_assets`] reach the browser (the HTTP response framing), keeping the //! raw asset bytes (`web_assets`) separate from delivery concerns. The server //! depends on this crate, not on `web_assets` directly. pub use web_assets::{resolve, Asset}; /// Build a complete HTTP/1.1 response for a static GET path. Returns `None` /// for unknown paths so the caller can emit a 404. pub fn http_response(path: &str) -> Option> { let asset = resolve(path)?; let body = asset.body.as_bytes(); let mut out = Vec::with_capacity(body.len() + 128); let header = format!( "HTTP/1.1 200 OK\r\nContent-Type: {}\r\nContent-Length: {}\r\nCache-Control: no-cache\r\nConnection: close\r\n\r\n", asset.content_type, body.len() ); out.extend_from_slice(header.as_bytes()); out.extend_from_slice(body); Some(out) } /// The canonical 404 response. pub fn not_found() -> Vec { let body = b"404 not found"; let mut out = Vec::new(); let header = format!( "HTTP/1.1 404 Not Found\r\nContent-Type: text/plain\r\nContent-Length: {}\r\nConnection: close\r\n\r\n", body.len() ); out.extend_from_slice(header.as_bytes()); out.extend_from_slice(body); out } #[cfg(test)] mod tests { use super::*; #[test] fn serves_shell() { let r = http_response("/").unwrap(); let s = String::from_utf8_lossy(&r); assert!(s.starts_with("HTTP/1.1 200 OK")); assert!(s.contains("text/html")); assert!(s.contains("Magicka VM")); } #[test] fn unknown_path_is_none() { assert!(http_response("/secret").is_none()); } }