WireframeApp supports optional setup and teardown callbacks that run once per
connection. Setup can return arbitrary state retained until teardown executes
after the stream finishes processing.[^2] During handle_connection the
framework caches middleware chains, enforces read timeouts, and records metrics
for inbound frames, serialization failures, and handler errors before logging
warnings.[^6][^7] PacketParts::inherit_correlation ensures response packets
carry the correct correlation identifier even when middleware omits it.[^8]
Immediate responses are available through send_response and
send_response_framed, both of which report serialization or I/O problems via
SendError.[^6][^5]
use tokio::io::{self, AsyncReadExt, AsyncWriteExt};
use wireframe::{
app::{SendError, WireframeApp},
message::Message,
};
#[derive(bincode::Encode, bincode::BorrowDecode, Debug, PartialEq)]
struct Ready(&'static str);
#[tokio::main]
async fn main() -> Result<(), SendError> {
let app = WireframeApp::default();
let (mut client, mut server) = io::duplex(64);
let ready = Ready("ready");
app.send_response(&mut server, &ready).await?;
server.shutdown().await?;
let mut buffer = Vec::new();
client.read_to_end(&mut buffer).await?;
let (decoded, _) = Ready::from_bytes(&buffer).expect("decode Ready frame");
assert_eq!(decoded, ready);
Ok(())
}