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§
Sourcefn 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,
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§
Sourcefn auth(&self) -> &AuthHandler
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.
}
}
Sourcefn middleware(&self) -> &MiddlewareSet
fn middleware(&self) -> &MiddlewareSet
Configure middleware on this controller. Global middleware can be set in the configuration. By default, controllers have no middleware.
Sourcefn skip_csrf(&self) -> bool
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.
Sourcefn route(self, path: &str) -> Handlerwhere
Self: Sized + 'static,
fn route(self, path: &str) -> Handlerwhere
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)
Sourcefn wildcard(self, path: &str) -> Handlerwhere
Self: Sized + 'static,
fn wildcard(self, path: &str) -> Handlerwhere
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
.
Sourcefn 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_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.
Sourcefn 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 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.
Sourcefn controller_name(&self) -> &'static str
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.