#[derive(FromRequest)]
{
    // Attributes available to this derive:
    #[from_request]
}
Expand description

Derive an implementation of FromRequest.

Supports generating two kinds of implementations:

  1. One that extracts each field individually.
  2. Another that extracts the whole type at once via another extractor.

Each field individually

By default #[derive(FromRequest)] will call FromRequest::from_request for each field:

use axum_macros::FromRequest;
use axum::{
    extract::{Extension, TypedHeader},
    headers::ContentType,
    body::Bytes,
};

#[derive(FromRequest)]
struct MyExtractor {
    state: Extension<State>,
    content_type: TypedHeader<ContentType>,
    request_body: Bytes,
}

#[derive(Clone)]
struct State {
    // ...
}

async fn handler(extractor: MyExtractor) {}

This requires that each field is an extractor (i.e. implements FromRequest).

Extracting via another extractor

You can use #[from_request(via(...))] to extract a field via another extractor, meaning the field itself doesn’t need to implement FromRequest:

use axum_macros::FromRequest;
use axum::{
    extract::{Extension, TypedHeader},
    headers::ContentType,
    body::Bytes,
};

#[derive(FromRequest)]
struct MyExtractor {
    // This will extracted via `Extension::<State>::from_request`
    #[from_request(via(Extension))]
    state: State,
    // and this via `TypedHeader::<ContentType>::from_request`
    #[from_request(via(TypedHeader))]
    content_type: ContentType,
    // Can still be combined with other extractors
    request_body: Bytes,
}

#[derive(Clone)]
struct State {
    // ...
}

async fn handler(extractor: MyExtractor) {}

Note this requires the via extractor to be a generic newtype struct (a tuple struct with exactly one public field) that implements FromRequest:

pub struct ViaExtractor<T>(pub T);

// impl<T, B> FromRequest<B> for ViaExtractor<T> { ... }

More complex via extractors are not supported and require writing a manual implementation.

Optional fields

#[from_request(via(...))] supports Option<_> and Result<_, _> to make fields optional:

use axum_macros::FromRequest;
use axum::{
    extract::{TypedHeader, rejection::TypedHeaderRejection},
    headers::{ContentType, UserAgent},
};

#[derive(FromRequest)]
struct MyExtractor {
    // This will extracted via `Option::<TypedHeader<ContentType>>::from_request`
    #[from_request(via(TypedHeader))]
    content_type: Option<ContentType>,
    // This will extracted via
    // `Result::<TypedHeader<UserAgent>, TypedHeaderRejection>::from_request`
    #[from_request(via(TypedHeader))]
    user_agent: Result<UserAgent, TypedHeaderRejection>,
}

async fn handler(extractor: MyExtractor) {}

The rejection

A rejection enum is also generated. It has a variant for each field:

use axum_macros::FromRequest;
use axum::{
    extract::{Extension, TypedHeader},
    headers::ContentType,
    body::Bytes,
};

#[derive(FromRequest)]
struct MyExtractor {
    #[from_request(via(Extension))]
    state: State,
    #[from_request(via(TypedHeader))]
    content_type: ContentType,
    request_body: Bytes,
}

// also generates
//
// #[derive(Debug)]
// enum MyExtractorRejection {
//     State(ExtensionRejection),
//     ContentType(TypedHeaderRejection),
//     RequestBody(BytesRejection),
// }
//
// impl axum::response::IntoResponse for MyExtractor { ... }
//
// impl std::fmt::Display for MyExtractor { ... }
//
// impl std::error::Error for MyExtractor { ... }

#[derive(Clone)]
struct State {
    // ...
}

The rejection’s std::error::Error::source implementation returns the inner rejection. This can be used to access source errors for example to customize rejection responses. Note this means the inner rejection types must themselves implement std::error::Error. All extractors in axum does this.

You can opt out of this using #[from_request(rejection_derive(...))]:

use axum_macros::FromRequest;
use axum::{
    extract::{FromRequest, RequestParts},
    http::StatusCode,
    headers::ContentType,
    body::Bytes,
    async_trait,
};

#[derive(FromRequest)]
#[from_request(rejection_derive(!Display, !Error))]
struct MyExtractor {
    other: OtherExtractor,
}

struct OtherExtractor;

#[async_trait]
impl<B> FromRequest<B> for OtherExtractor
where
    B: Send + 'static,
{
    // this rejection doesn't implement `Display` and `Error`
    type Rejection = (StatusCode, String);

    async fn from_request(_req: &mut RequestParts<B>) -> Result<Self, Self::Rejection> {
        // ...
    }
}

The whole type at once

By using #[from_request(via(...))] on the container you can extract the whole type at once, instead of each field individually:

use axum_macros::FromRequest;
use axum::extract::Extension;

// This will extracted via `Extension::<State>::from_request`
#[derive(Clone, FromRequest)]
#[from_request(via(Extension))]
struct State {
    // ...
}

async fn handler(state: State) {}

The rejection will be the “via extractors”’s rejection. For the previous example that would be axum::extract::rejection::ExtensionRejection.

Known limitations

Generics are currently not supported:

#[derive(axum_macros::FromRequest)]
struct MyExtractor<T> {
    thing: Option<T>,
}