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§
Sourcefn 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 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.
Provided Methods§
Sourcefn actus_describe_routes(&self) -> Vec<RouteDef>
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.
Sourcefn actus_max_body_bytes(&self) -> Option<usize>
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.)
Sourcefn actus_rate_limit(&self) -> Option<&'static str>
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".