Trait axum::handler::Handler

source ·
pub trait Handler<T, S, B = Body>:
    Clone
    + Send
    + Sized
    + 'static {
    type Future: Future<Output = Response> + Send + 'static;

    // Required method
    fn call(self, req: Request<B>, state: S) -> Self::Future;

    // Provided methods
    fn layer<L, NewReqBody>(
        self,
        layer: L,
    ) -> Layered<L, Self, T, S, B, NewReqBody>
       where L: Layer<HandlerService<Self, T, S, B>> + Clone,
             L::Service: Service<Request<NewReqBody>> { ... }
    fn with_state(self, state: S) -> HandlerService<Self, T, S, B> { ... }
}
Expand description

Trait for async functions that can be used to handle requests.

You shouldn’t need to depend on this trait directly. It is automatically implemented to closures of the right types.

See the module docs for more details.

§Converting Handlers into Services

To convert Handlers into Services you have to call either HandlerWithoutStateExt::into_service or Handler::with_state:

use tower::Service;
use axum::{
    extract::State,
    body::Body,
    http::Request,
    handler::{HandlerWithoutStateExt, Handler},
};

// this handler doesn't require any state
async fn one() {}
// so it can be converted to a service with `HandlerWithoutStateExt::into_service`
assert_service(one.into_service());

// this handler requires state
async fn two(_: State<String>) {}
// so we have to provide it
let handler_with_state = two.with_state(String::new());
// which gives us a `Service`
assert_service(handler_with_state);

// helper to check that a value implements `Service`
fn assert_service<S>(service: S)
where
    S: Service<Request<Body>>,
{}

§Debugging handler type errors

For a function to be used as a handler it must implement the Handler trait. axum provides blanket implementations for functions that:

  • Are async fns.
  • Take no more than 16 arguments that all implement FromRequest.
  • Returns something that implements IntoResponse.
  • If a closure is used it must implement Clone + Send and be 'static.
  • Returns a future that is Send. The most common way to accidentally make a future !Send is to hold a !Send type across an await.

Unfortunately Rust gives poor error messages if you try to use a function that doesn’t quite match what’s required by Handler.

You might get an error like this:

error[E0277]: the trait bound `fn(bool) -> impl Future {handler}: Handler<_, _>` is not satisfied
   --> src/main.rs:13:44
    |
13  |     let app = Router::new().route("/", get(handler));
    |                                            ^^^^^^^ the trait `Handler<_, _>` is not implemented for `fn(bool) -> impl Future {handler}`
    |
   ::: axum/src/handler/mod.rs:116:8
    |
116 |     H: Handler<T, B>,
    |        ------------- required by this bound in `axum::routing::get`

This error doesn’t tell you why your function doesn’t implement Handler. It’s possible to improve the error with the debug_handler proc-macro from the axum-macros crate.

§Handlers that aren’t functions

The Handler trait is also implemented for T: IntoResponse. That allows easily returning fixed data for routes:

use axum::{
    Router,
    routing::{get, post},
    Json,
    http::StatusCode,
};
use serde_json::json;

let app = Router::new()
    // respond with a fixed string
    .route("/", get("Hello, World!"))
    // or return some mock data
    .route("/users", post((
        StatusCode::CREATED,
        Json(json!({ "id": 1, "username": "alice" })),
    )));

Required Associated Types§

source

type Future: Future<Output = Response> + Send + 'static

The type of future calling this handler returns.

Required Methods§

source

fn call(self, req: Request<B>, state: S) -> Self::Future

Call the handler with the given request.

Provided Methods§

source

fn layer<L, NewReqBody>(self, layer: L) -> Layered<L, Self, T, S, B, NewReqBody>
where L: Layer<HandlerService<Self, T, S, B>> + Clone, L::Service: Service<Request<NewReqBody>>,

Apply a tower::Layer to the handler.

All requests to the handler will be processed by the layer’s corresponding middleware.

This can be used to add additional processing to a request for a single handler.

Note this differs from routing::Router::layer which adds a middleware to a group of routes.

If you’re applying middleware that produces errors you have to handle the errors so they’re converted into responses. You can learn more about doing that here.

§Example

Adding the tower::limit::ConcurrencyLimit middleware to a handler can be done like so:

use axum::{
    routing::get,
    handler::Handler,
    Router,
};
use tower::limit::{ConcurrencyLimitLayer, ConcurrencyLimit};

async fn handler() { /* ... */ }

let layered_handler = handler.layer(ConcurrencyLimitLayer::new(64));
let app = Router::new().route("/", get(layered_handler));
source

fn with_state(self, state: S) -> HandlerService<Self, T, S, B>

Convert the handler into a Service by providing the state

Object Safety§

This trait is not object safe.

Implementors§

source§

impl<F, Fut, Res, S, B> Handler<((),), S, B> for F
where F: FnOnce() -> Fut + Clone + Send + 'static, Fut: Future<Output = Res> + Send, Res: IntoResponse, B: Send + 'static,

source§

impl<F, Fut, S, B, Res, M, T1> Handler<(M, T1), S, B> for F
where F: FnOnce(T1) -> Fut + Clone + Send + 'static, Fut: Future<Output = Res> + Send, B: Send + 'static, S: Send + Sync + 'static, Res: IntoResponse, T1: FromRequest<S, B, M> + Send,

source§

impl<F, Fut, S, B, Res, M, T1, T2> Handler<(M, T1, T2), S, B> for F
where F: FnOnce(T1, T2) -> Fut + Clone + Send + 'static, Fut: Future<Output = Res> + Send, B: Send + 'static, S: Send + Sync + 'static, Res: IntoResponse, T1: FromRequestParts<S> + Send, T2: FromRequest<S, B, M> + Send,

source§

impl<F, Fut, S, B, Res, M, T1, T2, T3> Handler<(M, T1, T2, T3), S, B> for F
where F: FnOnce(T1, T2, T3) -> Fut + Clone + Send + 'static, Fut: Future<Output = Res> + Send, B: Send + 'static, S: Send + Sync + 'static, Res: IntoResponse, T1: FromRequestParts<S> + Send, T2: FromRequestParts<S> + Send, T3: FromRequest<S, B, M> + Send,

source§

impl<F, Fut, S, B, Res, M, T1, T2, T3, T4> Handler<(M, T1, T2, T3, T4), S, B> for F
where F: FnOnce(T1, T2, T3, T4) -> Fut + Clone + Send + 'static, Fut: Future<Output = Res> + Send, B: Send + 'static, S: Send + Sync + 'static, Res: IntoResponse, T1: FromRequestParts<S> + Send, T2: FromRequestParts<S> + Send, T3: FromRequestParts<S> + Send, T4: FromRequest<S, B, M> + Send,

source§

impl<F, Fut, S, B, Res, M, T1, T2, T3, T4, T5> Handler<(M, T1, T2, T3, T4, T5), S, B> for F
where F: FnOnce(T1, T2, T3, T4, T5) -> Fut + Clone + Send + 'static, Fut: Future<Output = Res> + Send, B: Send + 'static, S: Send + Sync + 'static, Res: IntoResponse, T1: FromRequestParts<S> + Send, T2: FromRequestParts<S> + Send, T3: FromRequestParts<S> + Send, T4: FromRequestParts<S> + Send, T5: FromRequest<S, B, M> + Send,

source§

impl<F, Fut, S, B, Res, M, T1, T2, T3, T4, T5, T6> Handler<(M, T1, T2, T3, T4, T5, T6), S, B> for F
where F: FnOnce(T1, T2, T3, T4, T5, T6) -> Fut + Clone + Send + 'static, Fut: Future<Output = Res> + Send, B: Send + 'static, S: Send + Sync + 'static, Res: IntoResponse, T1: FromRequestParts<S> + Send, T2: FromRequestParts<S> + Send, T3: FromRequestParts<S> + Send, T4: FromRequestParts<S> + Send, T5: FromRequestParts<S> + Send, T6: FromRequest<S, B, M> + Send,

source§

impl<F, Fut, S, B, Res, M, T1, T2, T3, T4, T5, T6, T7> Handler<(M, T1, T2, T3, T4, T5, T6, T7), S, B> for F
where F: FnOnce(T1, T2, T3, T4, T5, T6, T7) -> Fut + Clone + Send + 'static, Fut: Future<Output = Res> + Send, B: Send + 'static, S: Send + Sync + 'static, Res: IntoResponse, T1: FromRequestParts<S> + Send, T2: FromRequestParts<S> + Send, T3: FromRequestParts<S> + Send, T4: FromRequestParts<S> + Send, T5: FromRequestParts<S> + Send, T6: FromRequestParts<S> + Send, T7: FromRequest<S, B, M> + Send,

source§

impl<F, Fut, S, B, Res, M, T1, T2, T3, T4, T5, T6, T7, T8> Handler<(M, T1, T2, T3, T4, T5, T6, T7, T8), S, B> for F
where F: FnOnce(T1, T2, T3, T4, T5, T6, T7, T8) -> Fut + Clone + Send + 'static, Fut: Future<Output = Res> + Send, B: Send + 'static, S: Send + Sync + 'static, Res: IntoResponse, T1: FromRequestParts<S> + Send, T2: FromRequestParts<S> + Send, T3: FromRequestParts<S> + Send, T4: FromRequestParts<S> + Send, T5: FromRequestParts<S> + Send, T6: FromRequestParts<S> + Send, T7: FromRequestParts<S> + Send, T8: FromRequest<S, B, M> + Send,

source§

impl<F, Fut, S, B, Res, M, T1, T2, T3, T4, T5, T6, T7, T8, T9> Handler<(M, T1, T2, T3, T4, T5, T6, T7, T8, T9), S, B> for F
where F: FnOnce(T1, T2, T3, T4, T5, T6, T7, T8, T9) -> Fut + Clone + Send + 'static, Fut: Future<Output = Res> + Send, B: Send + 'static, S: Send + Sync + 'static, Res: IntoResponse, T1: FromRequestParts<S> + Send, T2: FromRequestParts<S> + Send, T3: FromRequestParts<S> + Send, T4: FromRequestParts<S> + Send, T5: FromRequestParts<S> + Send, T6: FromRequestParts<S> + Send, T7: FromRequestParts<S> + Send, T8: FromRequestParts<S> + Send, T9: FromRequest<S, B, M> + Send,

source§

impl<F, Fut, S, B, Res, M, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> Handler<(M, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10), S, B> for F
where F: FnOnce(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) -> Fut + Clone + Send + 'static, Fut: Future<Output = Res> + Send, B: Send + 'static, S: Send + Sync + 'static, Res: IntoResponse, T1: FromRequestParts<S> + Send, T2: FromRequestParts<S> + Send, T3: FromRequestParts<S> + Send, T4: FromRequestParts<S> + Send, T5: FromRequestParts<S> + Send, T6: FromRequestParts<S> + Send, T7: FromRequestParts<S> + Send, T8: FromRequestParts<S> + Send, T9: FromRequestParts<S> + Send, T10: FromRequest<S, B, M> + Send,

source§

impl<F, Fut, S, B, Res, M, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11> Handler<(M, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11), S, B> for F
where F: FnOnce(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11) -> Fut + Clone + Send + 'static, Fut: Future<Output = Res> + Send, B: Send + 'static, S: Send + Sync + 'static, Res: IntoResponse, T1: FromRequestParts<S> + Send, T2: FromRequestParts<S> + Send, T3: FromRequestParts<S> + Send, T4: FromRequestParts<S> + Send, T5: FromRequestParts<S> + Send, T6: FromRequestParts<S> + Send, T7: FromRequestParts<S> + Send, T8: FromRequestParts<S> + Send, T9: FromRequestParts<S> + Send, T10: FromRequestParts<S> + Send, T11: FromRequest<S, B, M> + Send,

source§

impl<F, Fut, S, B, Res, M, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12> Handler<(M, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12), S, B> for F
where F: FnOnce(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12) -> Fut + Clone + Send + 'static, Fut: Future<Output = Res> + Send, B: Send + 'static, S: Send + Sync + 'static, Res: IntoResponse, T1: FromRequestParts<S> + Send, T2: FromRequestParts<S> + Send, T3: FromRequestParts<S> + Send, T4: FromRequestParts<S> + Send, T5: FromRequestParts<S> + Send, T6: FromRequestParts<S> + Send, T7: FromRequestParts<S> + Send, T8: FromRequestParts<S> + Send, T9: FromRequestParts<S> + Send, T10: FromRequestParts<S> + Send, T11: FromRequestParts<S> + Send, T12: FromRequest<S, B, M> + Send,

source§

impl<F, Fut, S, B, Res, M, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13> Handler<(M, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13), S, B> for F
where F: FnOnce(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13) -> Fut + Clone + Send + 'static, Fut: Future<Output = Res> + Send, B: Send + 'static, S: Send + Sync + 'static, Res: IntoResponse, T1: FromRequestParts<S> + Send, T2: FromRequestParts<S> + Send, T3: FromRequestParts<S> + Send, T4: FromRequestParts<S> + Send, T5: FromRequestParts<S> + Send, T6: FromRequestParts<S> + Send, T7: FromRequestParts<S> + Send, T8: FromRequestParts<S> + Send, T9: FromRequestParts<S> + Send, T10: FromRequestParts<S> + Send, T11: FromRequestParts<S> + Send, T12: FromRequestParts<S> + Send, T13: FromRequest<S, B, M> + Send,

source§

impl<F, Fut, S, B, Res, M, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14> Handler<(M, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14), S, B> for F
where F: FnOnce(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14) -> Fut + Clone + Send + 'static, Fut: Future<Output = Res> + Send, B: Send + 'static, S: Send + Sync + 'static, Res: IntoResponse, T1: FromRequestParts<S> + Send, T2: FromRequestParts<S> + Send, T3: FromRequestParts<S> + Send, T4: FromRequestParts<S> + Send, T5: FromRequestParts<S> + Send, T6: FromRequestParts<S> + Send, T7: FromRequestParts<S> + Send, T8: FromRequestParts<S> + Send, T9: FromRequestParts<S> + Send, T10: FromRequestParts<S> + Send, T11: FromRequestParts<S> + Send, T12: FromRequestParts<S> + Send, T13: FromRequestParts<S> + Send, T14: FromRequest<S, B, M> + Send,

source§

impl<F, Fut, S, B, Res, M, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15> Handler<(M, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15), S, B> for F
where F: FnOnce(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15) -> Fut + Clone + Send + 'static, Fut: Future<Output = Res> + Send, B: Send + 'static, S: Send + Sync + 'static, Res: IntoResponse, T1: FromRequestParts<S> + Send, T2: FromRequestParts<S> + Send, T3: FromRequestParts<S> + Send, T4: FromRequestParts<S> + Send, T5: FromRequestParts<S> + Send, T6: FromRequestParts<S> + Send, T7: FromRequestParts<S> + Send, T8: FromRequestParts<S> + Send, T9: FromRequestParts<S> + Send, T10: FromRequestParts<S> + Send, T11: FromRequestParts<S> + Send, T12: FromRequestParts<S> + Send, T13: FromRequestParts<S> + Send, T14: FromRequestParts<S> + Send, T15: FromRequest<S, B, M> + Send,

source§

impl<F, Fut, S, B, Res, M, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16> Handler<(M, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16), S, B> for F
where F: FnOnce(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16) -> Fut + Clone + Send + 'static, Fut: Future<Output = Res> + Send, B: Send + 'static, S: Send + Sync + 'static, Res: IntoResponse, T1: FromRequestParts<S> + Send, T2: FromRequestParts<S> + Send, T3: FromRequestParts<S> + Send, T4: FromRequestParts<S> + Send, T5: FromRequestParts<S> + Send, T6: FromRequestParts<S> + Send, T7: FromRequestParts<S> + Send, T8: FromRequestParts<S> + Send, T9: FromRequestParts<S> + Send, T10: FromRequestParts<S> + Send, T11: FromRequestParts<S> + Send, T12: FromRequestParts<S> + Send, T13: FromRequestParts<S> + Send, T14: FromRequestParts<S> + Send, T15: FromRequestParts<S> + Send, T16: FromRequest<S, B, M> + Send,

source§

impl<H, S, T, L, B, B2> Handler<T, S, B2> for Layered<L, H, T, S, B, B2>
where L: Layer<HandlerService<H, T, S, B>> + Clone + Send + 'static, H: Handler<T, S, B>, L::Service: Service<Request<B2>, Error = Infallible> + Clone + Send + 'static, <L::Service as Service<Request<B2>>>::Response: IntoResponse, <L::Service as Service<Request<B2>>>::Future: Send, T: 'static, S: 'static, B: Send + 'static, B2: Send + 'static,

source§

type Future = LayeredFuture<B2, <L as Layer<HandlerService<H, T, S, B>>>::Service>

source§

impl<S, B> Handler<(), S, B> for MethodRouter<S, B>
where S: Clone + 'static, B: HttpBody + Send + 'static,