Skip to main content

Controller

Trait Controller 

Source
pub trait Controller: Send + Sync {
    // Required methods
    fn actus_dispatch<'life0, 'life1, 'async_trait>(
        &'life0 self,
        action: &'life1 str,
        params: Params,
    ) -> Pin<Box<dyn Future<Output = Reply> + Send + 'async_trait>>
       where Self: 'async_trait,
             'life0: 'async_trait,
             'life1: 'async_trait;
    fn __name(&self) -> &'static str;

    // Provided methods
    fn actus_describe_routes(&self) -> Vec<RouteDef> { ... }
    fn actus_max_body_bytes(&self) -> Option<usize> { ... }
    fn actus_rate_limit(&self) -> Option<&'static str> { ... }
}
Expand description

The runtime interface every controller implements. Hand-writing this is possible but unusual — the #[controller] macro generates the implementation (dispatch table, parameter extraction, the metadata methods) from a controller’s impl block and its routes! declaration.

Required Methods§

Source

fn actus_dispatch<'life0, 'life1, 'async_trait>( &'life0 self, action: &'life1 str, params: Params, ) -> Pin<Box<dyn Future<Output = Reply> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Route action (the path below this controller’s mount) to the matching handler and run it, returning its Reply. Generated by the macro.

Source

fn __name(&self) -> &'static str

The controller’s type name, for diagnostics and route auditing.

Provided Methods§

Source

fn actus_describe_routes(&self) -> Vec<RouteDef>

The controller’s declared routes, for introspection (OpenAPI generation, route audits). Defaults to empty; the macro overrides it.

Source

fn actus_max_body_bytes(&self) -> Option<usize>

Per-controller maximum buffered body size, in bytes. Returned by the #[controller(max_body_bytes = …)] attribute when set; None means the controller defers to the server-level cap (Server::with_max_body_bytes).

Resolution at request time (see Server::handle_request_inner): controller value if Some, otherwise the server-wide cap, otherwise DEFAULT_MAX_BODY_BYTES (2 MiB).

The framework calls this before buffering the body — so a 1 KB controller cap rejects a 50 KB request before the bytes are allocated. (A request body big enough to be a memory concern shouldn’t get past the framework regardless of where the handler would have rejected it.)

Source

fn actus_rate_limit(&self) -> Option<&'static str>

Per-controller rate-limit class label, as declared by #[controller(rate_limit = "name")]. None (the default) means the controller declared no class.

This is a label, not a policy. Actus is policy-agnostic: it ships no limiter algorithm, key function, or store, because the framework can’t pick those correctly for someone else (which key — IP / user / API key? which algorithm — token bucket / sliding window? which store — in-memory / Redis?). Those are application decisions, so the limiter itself stays an application Middleware.

What the framework does own is auditability and the response shape. The server stamps this label onto the matched request (surfaced as Request::rate_limit_class in actus-server), so a reviewer can read each endpoint’s rate-limit class straight off the #[controller(...)] line, and an application’s rate-limit Middleware can map class → policy and reject over-limit requests with WebError::TooManyRequests (429 + Retry-After, also framework-owned). Two controllers sharing a class share a limit namespace; what each class means is the application’s call.

Resolution is per-controller, mirroring Controller::actus_max_body_bytes. A per-route override would be an additive future change (the same shape as the per-route body-cap proposal).

Dyn Compatibility§

This trait is dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementors§