Expand description
Controller trait — pure descriptor for composable route groups.
A Controller is a zero-knowledge marker type. It knows only two things:
type State— the service it needs (Arc<State>is resolved and passed in)fn mount— a Kleisli arrowArc<State> -> (Router -> Result<Router>)
Controllers have no dependency on Router, RouteSet, or any DI
container. The mount_handlers! macro generates the mount
implementation from a simple list of (route_constant, handler_fn) pairs.
Users only write handlers.
§Kleisli Composition
mount returns impl FnOnce(Router<()>) -> Result<Router<()>> — a Kleisli
arrow in the Result monad. The RouterPipeline composes these arrows with
and_then (>>=), threading the router through each controller in
sequence. A failed arrow short-circuits the rest.
§Immutability Contract
State is passed as Arc<S> — shared, immutable after construction. Services
must not expose &mut self methods. All state mutation goes through
Atomic* primitives or channels (never Mutex<T> on the service struct).
§Example
pub struct HealthController;
#[get("/health")]
pub async fn health_check(State(svc): State<Arc<HealthService>>) -> Json<HealthResponse> {
Json(svc.health_check())
}
// mount_handlers! generates the full Controller impl — user never writes Router.
mount_handlers!(HealthController, HealthService, [
(__health_check_route, health_check),
]);Traits§
- Controller
- A pure descriptor for a group of HTTP routes sharing a common service dependency.