beet_net
beet_net generalises the Request/Response pattern and cuts it loose from any single transport. A request has a path, params and a body; a response has a status code and a body. Nothing in that shape mentions HTTP.
Once an exchange is just data, the transport becomes a swappable detail. The same handler can sit behind a CliServer reading command-line arguments or an HttpServer taking HTTP requests, with the only change being which server you spawn.
use beet_net::prelude::*;
use beet_core::prelude::*;
App::new()
.add_plugins((MinimalPlugins, ServerPlugin))
.add_systems(Startup, |mut commands: Commands| {
commands.spawn((
// swap CliServer for HttpServer to take HTTP requests instead
CliServer::default(),
exchange_handler(|_| {
Response::ok_body("hello world", MediaType::Text)
}),
));
})
.run();
So a beet app's --help flag, its HTTP sitemap and its AI tool definitions can be the same thing. Around that core, beet_net provides cross-platform HTTP clients (ureq, reqwest and a wasm backend), object storage over filesystems or S3, WebSockets, and SSH, each behind a feature flag so the dependency footprint stays small. Handlers themselves are Action<Request, Response> values from beet_action, which is how routing in beet_router builds on top.