mirror of
https://github.com/tokio-rs/axum.git
synced 2026-08-24 00:00:16 +02:00
68 lines
1.7 KiB
Rust
68 lines
1.7 KiB
Rust
use super::{rejection::*, FromRequest, RequestParts};
|
|||
|
|
use async_trait::async_trait;
|
||
|
|
use serde::de::DeserializeOwned;
|
||
|
|
use std::ops::Deref;
|
||
|
|
|
||
|
|
/// Extractor that deserializes query strings into some type.
|
||
|
|
///
|
||
|
|
/// `T` is expected to implement [`serde::Deserialize`].
|
||
|
|
///
|
||
|
|
/// # Example
|
||
|
|
///
|
||
|
|
/// ```rust,no_run
|
||
|
|
/// use axum::prelude::*;
|
||
|
|
/// use serde::Deserialize;
|
||
|
|
///
|
||
|
|
/// #[derive(Deserialize)]
|
||
|
|
/// struct Pagination {
|
||
|
|
/// page: usize,
|
||
|
|
/// per_page: usize,
|
||
|
|
/// }
|
||
|
|
///
|
||
|
|
/// // This will parse query strings like `?page=2&per_page=30` into `Pagination`
|
||
|
|
/// // structs.
|
||
|
|
/// async fn list_things(pagination: extract::Query<Pagination>) {
|
||
|
|
/// let pagination: Pagination = pagination.0;
|
||
|
|
///
|
||
|
|
/// // ...
|
||
|
|
/// }
|
||
|
|
///
|
||
|
|
/// let app = route("/list_things", get(list_things));
|
||
|
|
/// # async {
|
||
|
|
/// # hyper::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
|
||
|
|
/// # };
|
||
|
|
/// ```
|
||
|
|
///
|
||
|
|
/// If the query string cannot be parsed it will reject the request with a `400
|
||
|
|
/// Bad Request` response.
|
||
|
|
#[derive(Debug, Clone, Copy, Default)]
|
||
|
|
pub struct Query<T>(pub T);
|
||
|
|
|
||
|
|
#[async_trait]
|
||
|
|
impl<T, B> FromRequest<B> for Query<T>
|
||
|
|
where
|
||
|
|
T: DeserializeOwned,
|
||
|
|
B: Send,
|
||
|
|
{
|
||
|
|
type Rejection = QueryRejection;
|
||
|
|
|
||
|
|
async fn from_request(req: &mut RequestParts<B>) -> Result<Self, Self::Rejection> {
|
||
|
|
let query = req
|
||
|
|
.uri()
|
||
|
|
.ok_or(UriAlreadyExtracted)?
|
||
|
|
.query()
|
||
|
|
.ok_or(QueryStringMissing)?;
|
||
|
|
let value = serde_urlencoded::from_str(query)
|
||
|
|
.map_err(FailedToDeserializeQueryString::new::<T, _>)?;
|
||
|
|
Ok(Query(value))
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
impl<T> Deref for Query<T> {
|
||
|
|
type Target = T;
|
||
|
|
|
||
|
|
fn deref(&self) -> &Self::Target {
|
||
|
|
&self.0
|
||
|
|
}
|
||
|
|
}
|