Trait Controller

Source
pub trait Controller: Sync + Send {
    // Required method
    fn handle<'life0, 'life1, 'async_trait>(
        &'life0 self,
        request: &'life1 Request,
    ) -> Pin<Box<dyn Future<Output = Result<Response, Error>> + Send + 'async_trait>>
       where Self: 'async_trait,
             'life0: 'async_trait,
             'life1: 'async_trait;

    // Provided methods
    fn auth(&self) -> &AuthHandler { ... }
    fn middleware(&self) -> &MiddlewareSet { ... }
    fn skip_csrf(&self) -> bool { ... }
    fn route(self, path: &str) -> Handler
       where Self: Sized + 'static { ... }
    fn wildcard(self, path: &str) -> Handler
       where Self: Sized + 'static { ... }
    fn handle_stream<'life0, 'life1, 'life2, 'async_trait>(
        &'life0 self,
        request: &'life1 Request,
        stream: Stream<'life2>,
    ) -> Pin<Box<dyn Future<Output = Result<bool, Error>> + Send + 'async_trait>>
       where Self: 'async_trait,
             'life0: 'async_trait,
             'life1: 'async_trait,
             'life2: 'async_trait { ... }
    fn handle_internal<'life0, 'async_trait>(
        &'life0 self,
        request: Request,
    ) -> Pin<Box<dyn Future<Output = Result<Response, Error>> + Send + 'async_trait>>
       where Self: 'async_trait,
             'life0: 'async_trait { ... }
    fn controller_name(&self) -> &'static str { ... }
}
Expand description

The controller, the C in MVC.

A controller handles an HTTP request routed to it by the server and returns a response. Controllers in Rwf are asynchronous and use the async_trait crate. For this reason, the trait signature looks a bit complicated, but underneath, all asynchronous functions are actually pretty simple.

§Handling requests

The only function that requires implementation is the Controller::handle method. It receives a Request and must return either a Response or an Error.

// Import required types and traits.
use rwf::prelude::*;

// A controller is a plain struct
// which implements the `Controller` trait.
struct Index;

// We use `async_trait` crate to handle async Rust traits.
#[async_trait]
impl Controller for Index {
    // This method responds to all requests routed
    // to this controller.
    async fn handle(&self, request: &Request) -> Result<Response, Error> {
        Ok(Response::new().html("<h1>Hello from Rwf!</h1>"))
    }
}

Required Methods§

Source

fn handle<'life0, 'life1, 'async_trait>( &'life0 self, request: &'life1 Request, ) -> Pin<Box<dyn Future<Output = Result<Response, Error>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Handle the request and return a response. Implement this function to define how your controller will respond to requests. This method is asynchronous, and since we use async_trait, the signature can be a bit confusing. The actual method is:

async fn handle(&self, request: &Request) -> Result<Response, Error>;

Provided Methods§

Source

fn auth(&self) -> &AuthHandler

Set the authentication mechanism for this controller. Default authentication method is to allow all requests, but can be adjusted through configuration.

§Example
use rwf::prelude::*;
use rwf::controller::DenyAll;

// The auth handler should be defined on the controller struct.
struct Index {
    auth: AuthHandler,
}

// Auth handlers need to be instantiated.
// Some like `BasicAuth` require parameters like username and password.
impl Default for Index {
    fn default() -> Self {
        Self {
            auth: AuthHandler::new(DenyAll {}),
        }
    }
}

#[async_trait]
impl Controller for Index {
    // Return the auth handler reference.
    fn auth(&self) -> &AuthHandler {
        &self.auth
    }

    async fn handle(&self, request: &Request) -> Result<Response, Error> {
        todo!() // Handle request.
    }
}
Source

fn middleware(&self) -> &MiddlewareSet

Configure middleware on this controller. Global middleware can be set in the configuration. By default, controllers have no middleware.

Source

fn skip_csrf(&self) -> bool

Don’t use CSRF protection on this controller. You generally don’t want to disable this unless you have another mechanism to make sure your users are not being duped into making requests to your app from somewhere else.

Source

fn route(self, path: &str) -> Handler
where Self: Sized + 'static,

Create a basic route handler for this controller.

This method can be used to register a controller with the HTTP server.

§Example
Index::new().route("/")

is equivalent to using the rwf_macros::route macro:

route!("/" => Index)
Source

fn wildcard(self, path: &str) -> Handler
where Self: Sized + 'static,

Create a wildcard route handler for this controller.

A wildcard handler will serve all requests that match this path and all paths that have this path as its parent. For example, if the path is set to /users, all paths that start with /users, like /users/account, /users/5, etc., will be served by this controller.

This is useful for creating catch-all controllers, and the handler will have the lowest rank in the crate::http::Router.

Source

fn handle_stream<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, request: &'life1 Request, stream: Stream<'life2>, ) -> Pin<Box<dyn Future<Output = Result<bool, Error>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Internal function that handlers the TCP connection directly after a response has been sent to the client by the controller. This is typically used for WebSocket connections, but can also be used to stream data like video.

Source

fn handle_internal<'life0, 'async_trait>( &'life0 self, request: Request, ) -> Pin<Box<dyn Future<Output = Result<Response, Error>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Internal function which implements the bulk of Rwf controller logic. Do not implement this unless you’re looking to do something entirely different.

Things handled by this method:

  • Checking authentication
  • Running middleware
  • Ensuring each request has a session

Controllers that override this need to be aware of the internal functionality of Rwf and act accordingly.

Source

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

The name of this controller. Used for logging. All names are globally unique, so you won’t need to override this method.

Implementors§