Skip to content

Request handlers

A request handler is invoked when a request matches on the associated method guard and path pattern. The request handler is in charge of building the response that will be sent back to the client.

use pavex::http::StatusCode;

pub fn greet() -> StatusCode {
    StatusCode::OK
}

Registration

You must provide an unambiguous path to the request handler, wrapped in the [f!][f] macro.

use pavex::blueprint::{router::GET, Blueprint};
use pavex::f;

pub fn blueprint() -> Blueprint {
    let mut bp = Blueprint::new();
    bp.route(GET, "/greet", f!(crate::routes::greet));
    bp
}

The path must be wrapped in the f! macro.

Registration syntax

You can use free functions, static methods, non-static methods, and trait methods as request handlers. Check out the dependency injection cookbook for more details on the syntax for each case.

IntoResponse

A request handler must return a type that can be converted into a Response via the IntoResponse trait.
You only have three first-party types to choose from:

This is an explicit design choice. Pavex implements the IntoResponse trait exclusively for types that don't require the framework to assume or infer a suitable status code.

If you want to return a custom type from your request handler, you must implement IntoResponse for it.

Dependency injection

Request handlers are expected to take into account the incoming request when building the response. How does that work in Pavex? How do you extract data from the request?

You must take advantage of dependency injection.

You must specify the dependencies of your request handler as input parameters in its function signature.
Those inputs are going to be built and injected by the framework, according to the constructors you have registered.

Check out the dependency injection guide for more details on how the process works.
Check out the request data guide for an overview of the data you can extract from the request using Pavex's first-party extractors.

Request handlers can fail

Your request handlers can be fallible, i.e. they can return a Result.

pub async fn greet(/* ... */) -> Result<Response, GreetError> {
    // ...
}

If they do, you must specify an error handler when registering the route:

use pavex::blueprint::{router::GET, Blueprint};
use pavex::f;

pub fn blueprint() -> Blueprint {
    let mut bp = Blueprint::new();
    bp.route(GET, "/greet", f!(crate::routes::greet))
        .error_handler(f!(crate::error_handler::greet_error_handler));
    bp
}

Check out the error handling guide for more details.

Sync or async?

Request handlers can either be synchronous or asynchronous:

use pavex::http::StatusCode;

pub async fn async_greet() -> StatusCode {
    StatusCode::OK
}

pub fn sync_greet() -> StatusCode {
    StatusCode::OK
}

There is no difference when registering the route with the Blueprint:

use pavex::blueprint::{router::GET, Blueprint};
use pavex::f;

pub fn blueprint() -> Blueprint {
    let mut bp = Blueprint::new();
    bp.route(GET, "/async_greet", f!(crate::routes::async_greet));
    bp.route(GET, "/sync_greet", f!(crate::routes::sync_greet));
    bp
}

Be careful with synchronous handlers: they block the thread they're running on until they return.
That's not a concern if you are performing an operation that's guaranteed to be fast (e.g. building a response from static data). It becomes a problem if you're doing work that's potentially slow. There are two types of work that can be slow:

  • I/O operations (e.g. reading from a file, querying a database, etc.)
  • CPU-intensive operations (e.g. computing a password hash, parsing a large file, etc.)

As a rule of thumb:

I/O CPU-intensive Handler type Notes
Yes No Async Use async libraries for the I/O portion. If the I/O interface is synchronous, use tokio::task::spawn_blocking.
No Yes Async Use tokio::task::spawn_blocking for the CPU-intensive portion.
Yes Yes Async See above.
No No Sync You can also make it asynchronous, it doesn't matter.

If you want to learn more about what "blocking" means in async Rust, check out Alice Rhyl's excellent article.