WebUI Rust Handler The webui crate provides high-performance build and rendering of WebUI protocols in Rust. It streams rendered HTML fragments via the ResponseWriter trait for progressive rendering with zero unnecessary allocations.
Installation Copy
[dependencies]
webui = "*" # see https://crates.io/crates/webui for latest version
serde_json = "1"
Examples Actix Web Axum Hyper
Copy
use actix_web::{web, App, HttpServer, HttpRequest, HttpResponse};
use webui::{WebUIHandler, RenderOptions, ResponseWriter, WebUIProtocol};
use serde_json::json;
use std::fs;
struct StringWriter(String);
impl ResponseWriter for StringWriter {
fn write (& mut self, content: & str ) -> webui_handler::Result<()> {
self.0. push_str(content);
Ok (())
}
fn end (& mut self) -> webui_handler::Result<()> { Ok (()) }
}
#[actix_web::main]
async fn main () -> std::io::Result<()> {
let protocol_bytes = fs::read(" ./dist/protocol.bin " ).unwrap();
let protocol = WebUIProtocol::from_protobuf(& protocol_bytes).unwrap();
let protocol = web::Data::new(protocol);
HttpServer::new(move | | {
App::new()
.app_data(protocol.clone())
.route(" /{path:.*} " , web::get().to(|proto: web::Data<WebUIProtocol>, req: HttpRequest| async move {
let state = json!({ " title " : " Home " });
let mut writer = StringWriter(String ::new());
let mut handler = WebUIHandler::new();
let options = RenderOptions::new(" index.html " , req.path());
handler.handle(& proto, & state, & options, & mut writer).unwrap();
HttpResponse::Ok().content_type(" text/html " ).body(writer.0 )
}))
})
.bind(" 127.0.0.1:3000 " )?
.run()
.await
}
Copy
use axum::{routing::get, Router, extract::{State, Request}};
use webui::{WebUIHandler, RenderOptions, ResponseWriter, WebUIProtocol};
use serde_json::json;
use std::{fs, sync::Arc};
struct StringWriter(String);
impl ResponseWriter for StringWriter {
fn write (& mut self, content: & str ) -> webui_handler::Result<()> {
self.0. push_str(content);
Ok (())
}
fn end (& mut self) -> webui_handler::Result<()> { Ok (()) }
}
#[tokio::main]
async fn main () {
let protocol_bytes = fs::read(" ./dist/protocol.bin " ).unwrap();
let protocol = Arc::new(WebUIProtocol::from_protobuf(& protocol_bytes).unwrap());
let app = Router::new()
.route(" /{*path} " , get(|State(proto): State<Arc<WebUIProtocol>>, req: Request| async move {
let state = json!({ " title " : " Home " });
let mut writer = StringWriter(String ::new());
let mut handler = WebUIHandler::new();
let options = RenderOptions::new(" index.html " , req.uri().path());
handler.handle(& proto, & state, & options, & mut writer).unwrap();
axum::response::Html(writer.0 )
}))
.with_state(protocol);
let listener = tokio::net::TcpListener::bind(" 127.0.0.1:3000 " ).await.unwrap();
axum::serve(listener, app).await.unwrap();
}
Copy
use hyper::{server::conn::http1, service::service_fn, body::Bytes, Request, Response};
use hyper_util::rt::TokioIo;
use http_body_util::Full;
use webui::{WebUIHandler, RenderOptions, ResponseWriter, WebUIProtocol};
use serde_json::json;
use std::{fs, sync::Arc};
struct StringWriter(String);
impl ResponseWriter for StringWriter {
fn write (& mut self, content: & str ) -> webui_handler::Result<()> {
self.0. push_str(content);
Ok (())
}
fn end (& mut self) -> webui_handler::Result<()> { Ok (()) }
}
#[tokio::main]
async fn main () {
let protocol_bytes = fs::read(" ./dist/protocol.bin " ).unwrap();
let protocol = Arc::new(WebUIProtocol::from_protobuf(& protocol_bytes).unwrap());
let listener = tokio::net::TcpListener::bind(" 127.0.0.1:3000 " ).await.unwrap();
loop {
let (stream, _ ) = listener.accept().await.unwrap();
let proto = protocol.clone();
tokio::spawn(async move {
http1::Builder::new()
.serve_connection(TokioIo::new(stream), service_fn(move | req: Request<_ >| {
let proto = proto.clone();
async move {
let state = json!({ " title " : " Home " });
let mut writer = StringWriter(String ::new());
let mut handler = WebUIHandler::new();
let options = RenderOptions::new(" index.html " , req.uri().path());
handler.handle(& proto, & state, & options, & mut writer).unwrap();
Ok ::<_ , hyper::Error>(Response::new(Full::new(Bytes::from(writer.0 ))))
}
}))
.await
.ok();
});
}
}
API Reference Build Function Description build(options)Build templates into a protocol. Returns BuildResult build_to_disk(options, out_dir)Build and write protocol.bin + CSS files to disk inspect(path)Read a protocol file and return JSON inspect_bytes(bytes)Convert protocol bytes to JSON
BuildOptions Field Type Default Description app_dirPathBuf- Path to app folder entryString"index.html"Entry file cssCssStrategyLinkCSS delivery: Link, Style, or Module pluginOption<String>NoneParser plugin (e.g. "fast-v3"; deprecated "fast"/"fast-v2" keep @microsoft/fast-element 2.x compatibility) componentsVec<String>[]External component sources
BuildStats Field Type Description durationDurationBuild time fragment_countusizeTotal fragments component_countusizeComponents registered css_file_countusizeCSS files produced protocol_size_bytesusizeProtocol binary size token_countusizeCSS tokens discovered