Handler

Handler is the specific object responsible for processing Request requests. Hander itself is a Trait, which contains an asynchronous method of handle:

#[async_trait]
pub trait Handler: Send + Sync + 'static {
    async fn handle(&self, req: &mut Request, depot: &mut Depot, res: &mut Response);
}

In many cases, you just want to use functions as Handler to process requests. You can add fn_handler to convert ordinary functions to Handler.

The default signature of the processing function contains three parameters, followed by &mut Request, &mut Depot. &mut Response. Depot is a temporary storage that can store data related to this request.

Middleware is actually a Handler, they can do some processing before or after the request arrives at the Handler that officially processes the request, such as login verification, data compression, etc.

The middleware is added through the before and after functions of the ``Router. The added middleware will affect the current Routerand its internal All descendants ofRouter```.

The most commonly used in normal projects should be fn_handler, it is a proc macro, adding to the function can turn the function into a Handler:

#[fn_handler]
async fn hello_world(req: &mut Request, depot: &mut Depot, res: &mut Response) {
    res.render_plain_text("Hello World");
}

If some parameters are not needed, they can be omitted directly. In fact, the order of these three parameters can be adjusted freely according to your preference, or any one or more parameters can be omitted. The following writing methods are all possible:

#[fn_handler]
async fn hello_world(req: &mut Request, res: &mut Response) {
}
#[fn_handler]
async fn hello_world(depot: &mut Depot) {
}
#[fn_handler]
async fn hello_world(res: &mut Response) {
}

fn_handler in Salvo can return Result, only the types of Ok and Err in Result are implemented Writer trait:

use salvo::anyhow;
use salvo::prelude::*;

struct CustomError;
#[async_trait]
impl Writer for CustomError {
    async fn write(mut self, _req: &mut Request, _depot: &mut Depot, res: &mut Response) {
        res.render_plain_text("custom error");
        res.set_http_error(InternalServerError());
    }
}

#[fn_handler]
async fn handle_anyhow() -> Result<(), anyhow::Error> {
    Err(anyhow::anyhow!("anyhow error"))
}
#[fn_handler]
async fn handle_custom() -> Result<(), CustomError> {
    Err(CustomError)
}

#[tokio::main]
async fn main() {
    let router = Router::new()
        .push(Router::new().path("anyhow").get(handle_anyhow))
        .push(Router::new().path("custom").get(handle_custom));
    Server::new(router).bind(([0, 0, 0, 0], 7878)).await;
}