lilydocs
HTTP APIWebSocketConsumer
Request processing2 min read

Guards

Check identity, permissions, or quota conditions before an action runs.

A guard decides whether an action is allowed to run. Its constructor is new(Arc<Extensions>), and its decision method is can_activate(&self, &mut Request, ExecutionCancellation).

Role-check example#

The following guard looks for the admin role in a verified principal. AuthGuard must complete authentication first.

AdminGuard
use std::sync::Arc;
use lilyrs::http_api::{
    ExecutionCancellation, Extensions, GuardInitError, GuardRejection,
    GuardTrait, HttpErrorCode, Principal, Request,
};

pub struct AdminGuard;

#[lilyrs::http_api::async_trait::async_trait]
impl GuardTrait for AdminGuard {
    async fn new(_: Arc<Extensions>) -> Result<Self, GuardInitError> { Ok(Self) }

    async fn can_activate(&self, request: &mut Request, _: ExecutionCancellation)
        -> Result<(), GuardRejection>
    {
        match request.principal() {
            Some(principal) if principal.has_role("admin") => Ok(()),
            Some(_) => Err(GuardRejection::forbidden(
                HttpErrorCode::new("ADMIN_REQUIRED").unwrap(),
            ).unwrap()),
            None => Err(GuardRejection::unauthorized(
                HttpErrorCode::new("AUTH_REQUIRED").unwrap(), "Bearer",
            ).unwrap()),
        }
    }
}

Attach to an action#

Action attributes
#[get("/admin")]
#[guard(AuthGuard, AdminGuard)]

Add these attributes to a controller action. Guards run from left to right. AuthGuard publishes the principal first, then AdminGuard checks its role.

Supply an instance#

AppBuilder::guard(instance) supplies a prebuilt instance of a particular type. This call alone does not run the guard on every endpoint. The corresponding action still needs #[guard(Type)]. If the same prebuilt type is supplied more than once, the last instance is used; CsrfGuard cannot be supplied this way.

Rejection contract#

GuardRejection uses the shared HttpRejection structure. It supports 401 challenges, 403, 429 / Retry-After, 503, bounded problem details, and JSON/text responses. Distinguish expected access denial from a technical runtime failure.

Sources for this page v0.1.0

This guide is based on the reviewed framework commit.

QUICK START
Documentation
Source code