Module axum::extract[][src]

Expand description

Types and traits for extracting data from requests.

A handler function is an async function take takes any number of “extractors” as arguments. An extractor is a type that implements FromRequest.

For example, Json is an extractor that consumes the request body and deserializes it as JSON into some target type:

use axum::prelude::*;
use serde::Deserialize;

#[derive(Deserialize)]
struct CreateUser {
    email: String,
    password: String,
}

async fn create_user(payload: extract::Json<CreateUser>) {
    let payload: CreateUser = payload.0;

    // ...
}

let app = route("/users", post(create_user));

Defining custom extractors

You can also define your own extractors by implementing FromRequest:

use axum::{async_trait, extract::{FromRequest, RequestParts}, prelude::*};
use http::{StatusCode, header::{HeaderValue, USER_AGENT}};

struct ExtractUserAgent(HeaderValue);

#[async_trait]
impl<B> FromRequest<B> for ExtractUserAgent
where
    B: Send,
{
    type Rejection = (StatusCode, &'static str);

    async fn from_request(req: &mut RequestParts<B>) -> Result<Self, Self::Rejection> {
        let user_agent = req.headers().and_then(|headers| headers.get(USER_AGENT));

        if let Some(user_agent) = user_agent {
            Ok(ExtractUserAgent(user_agent.clone()))
        } else {
            Err((StatusCode::BAD_REQUEST, "`User-Agent` header is missing"))
        }
    }
}

async fn handler(user_agent: ExtractUserAgent) {
    let user_agent: HeaderValue = user_agent.0;

    // ...
}

let app = route("/foo", get(handler));

Multiple extractors

Handlers can also contain multiple extractors:

use axum::prelude::*;
use std::collections::HashMap;

async fn handler(
    // Extract captured parameters from the URL
    params: extract::UrlParamsMap,
    // Parse query string into a `HashMap`
    query_params: extract::Query<HashMap<String, String>>,
    // Buffer the request body into a `Bytes`
    bytes: bytes::Bytes,
) {
    // ...
}

let app = route("/foo", get(handler));

Note that only one extractor can consume the request body. If multiple body extractors are applied a 500 Internal Server Error response will be returned.

Optional extractors

Wrapping extractors in Option will make them optional:

use axum::{extract::Json, prelude::*};
use serde_json::Value;

async fn create_user(payload: Option<Json<Value>>) {
    if let Some(payload) = payload {
        // We got a valid JSON payload
    } else {
        // Payload wasn't valid JSON
    }
}

let app = route("/users", post(create_user));

Wrapping extractors in Result makes them optional and gives you the reason the extraction failed:

use axum::{extract::{Json, rejection::JsonRejection}, prelude::*};
use serde_json::Value;

async fn create_user(payload: Result<Json<Value>, JsonRejection>) {
    match payload {
        Ok(payload) => {
            // We got a valid JSON payload
        }
        Err(JsonRejection::MissingJsonContentType(_)) => {
            // Request didn't have `Content-Type: application/json`
            // header
        }
        Err(JsonRejection::InvalidJsonBody(_)) => {
            // Couldn't deserialize the body into the target type
        }
        Err(JsonRejection::BodyAlreadyExtracted(_)) => {
            // Another extractor had already consumed the body
        }
        Err(_) => {
            // `JsonRejection` is marked `#[non_exhaustive]` so match must
            // include a catch-all case.
        }
    }
}

let app = route("/users", post(create_user));

Reducing boilerplate

If you’re feeling adventorous you can even deconstruct the extractors directly on the function signature:

use axum::{extract::Json, prelude::*};
use serde_json::Value;

async fn create_user(Json(value): Json<Value>) {
    // `value` is of type `Value`
}

let app = route("/users", post(create_user));

Request body extractors

Most of the time your request body type will be body::Body (a re-export of hyper::Body), which is directly supported by all extractors.

However if you’re applying a tower middleware that changes the response you might have to apply a different body type to some extractors:

use std::{
    task::{Context, Poll},
    pin::Pin,
};
use tower_http::map_request_body::MapRequestBodyLayer;
use axum::prelude::*;

struct MyBody<B>(B);

impl<B> http_body::Body for MyBody<B>
where
    B: http_body::Body + Unpin,
{
    type Data = B::Data;
    type Error = B::Error;

    fn poll_data(
        mut self: Pin<&mut Self>,
        cx: &mut Context<'_>,
    ) -> Poll<Option<Result<Self::Data, Self::Error>>> {
        Pin::new(&mut self.0).poll_data(cx)
    }

    fn poll_trailers(
        mut self: Pin<&mut Self>,
        cx: &mut Context<'_>,
    ) -> Poll<Result<Option<headers::HeaderMap>, Self::Error>> {
        Pin::new(&mut self.0).poll_trailers(cx)
    }
}

let app =
    // `String` works directly with any body type
    route(
        "/string",
        get(|_: String| async {})
    )
    .route(
        "/body",
        // `extract::Body` defaults to `axum::body::Body`
        // but can be customized
        get(|_: extract::Body<MyBody<Body>>| async {})
    )
    .route(
        "/body-stream",
        // same for `extract::BodyStream`
        get(|_: extract::BodyStream<MyBody<Body>>| async {}),
    )
    .route(
        // and `Request<_>`
        "/request",
        get(|_: Request<MyBody<Body>>| async {})
    )
    // middleware that changes the request body type
    .layer(MapRequestBodyLayer::new(MyBody));

Modules

Extractor for getting connection information from a client.

Convert an extractor into a middleware.

multipartmultipart

Extractor that parses multipart/form-data requests commonly used with file uploads.

Rejection response types.

Structs

Extractor that extracts the request body.

Extractor that extracts the request body as a Stream.

Extractor for getting connection information produced by a Connected.

Extractor that will reject requests with a body larger than some size.

Extractor that gets a value from request extensions.

Extractor that deserializes application/x-www-form-urlencoded requests into some type.

Extractor that deserializes request bodies into some type.

Extractor that parses multipart/form-data requests commonly used with file uploads.

Extractor that will get captures from the URL and parse them using serde.

Extractor that deserializes query strings into some type.

Extractor that extracts the raw query string, without parsing it.

The type used with FromRequest to extract data from requests.

Extractor that extracts a typed header value from headers.

UrlParamsDeprecated

Extractor that will get captures from the URL and parse them.

UrlParamsMapDeprecated

Extractor that will get captures from the URL.

Traits

Types that can be created from requests.

Functions

Convert an extractor into a middleware.