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::{
Json,
handler::{post, Handler},
Router,
};
use serde::Deserialize;
#[derive(Deserialize)]
struct CreateUser {
email: String,
password: String,
}
async fn create_user(payload: Json<CreateUser>) {
let payload: CreateUser = payload.0;
// ...
}
let app = Router::new().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},
handler::get,
Router,
};
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 = Router::new().route("/foo", get(handler));
Multiple extractors
Handlers can also contain multiple extractors:
use axum::{
extract::{Path, Query},
handler::get,
Router,
};
use std::collections::HashMap;
async fn handler(
// Extract captured parameters from the URL
params: Path<HashMap<String, String>>,
// Parse query string into a `HashMap`
query_params: Query<HashMap<String, String>>,
// Buffer the request body into a `Bytes`
bytes: bytes::Bytes,
) {
// ...
}
let app = Router::new().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,
handler::post,
Router,
};
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 = Router::new().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},
handler::post,
Router,
};
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 = Router::new().route("/users", post(create_user));
Reducing boilerplate
If you’re feeling adventurous you can even deconstruct the extractors directly on the function signature:
use axum::{
extract::Json,
handler::post,
Router,
};
use serde_json::Value;
async fn create_user(Json(value): Json<Value>) {
// `value` is of type `Value`
}
let app = Router::new().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::{
extract::{self, BodyStream},
body::Body,
handler::get,
http::{header::HeaderMap, Request},
Router,
};
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<HeaderMap>, Self::Error>> {
Pin::new(&mut self.0).poll_trailers(cx)
}
}
let app = Router::new()
.route(
"/string",
// `String` works directly with any body type
get(|_: String| async {})
)
.route(
"/body",
// `extract::Body` defaults to `axum::body::Body`
// but can be customized
get(|_: extract::RawBody<MyBody<Body>>| async {})
)
.route(
"/body-stream",
// same for `extract::BodyStream`
get(|_: extract::BodyStream| async {}),
)
.route(
// and `Request<_>`
"/request",
get(|_: Request<MyBody<Body>>| async {})
)
// middleware that changes the request body type
.layer(MapRequestBodyLayer::new(MyBody));
Re-exports
pub use crate::Json;
Modules
Extractor for getting connection information from a client.
Convert an extractor into a middleware.
multipart
Extractor that parses multipart/form-data
requests commonly used with file uploads.
Rejection response types.
ws
Handle WebSocket connections.
Structs
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 parses multipart/form-data
requests commonly used with file uploads.
Extractor that gets the original request URI regardless of nesting.
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 request body.
Extractor that extracts the raw query string, without parsing it.
The type used with FromRequest
to extract data from requests.
headers
Extractor that extracts a typed header value from headers
.
Extractor for establishing WebSocket connections.
Traits
Types that can be created from requests.
Functions
Convert an extractor into a middleware.