pub struct Query<T>(pub T);Expand description
Axum extractor that deserializes URL query parameters into T and then sanitizes it.
T must implement both serde::de::DeserializeOwned and crate::sanitize::Sanitize.
Repeated query keys deserialize into Vec<…> fields — for example ?tags=a&tags=b&tags=c
populates a tags: Vec<String> field with three elements. Nested keys
(?filter[status]=active) populate nested struct fields, and indexed brackets
(?items[0][id]=…) populate Vec<Struct> rows. Browsers that percent-encode
brackets (?filter%5Bstatus%5D=active, ?items%5B0%5D%5Bid%5D=…) decode to the
same shape — both forms are accepted.
Because this extractor implements FromRequestParts rather than FromRequest, it
can be combined with body extractors on the same handler. To make Query optional
(i.e. Option<Query<T>>), axum 0.8 requires an explicit OptionalFromRequestParts
impl — this crate does not provide one, so use a type whose fields are Option<_>
instead.
§Errors
The FromRequestParts::Rejection is crate::Error. A 400 Bad Request is
returned if the query string cannot be deserialized into T. The error renders via its
IntoResponse impl.
§Example
use modo::extractor::Query;
use modo::sanitize::Sanitize;
use serde::Deserialize;
#[derive(Deserialize)]
struct Filter { status: String, role: String }
#[derive(Deserialize)]
struct SearchParams {
q: String,
page: Option<u32>,
tags: Vec<String>, // ?tags=web&tags=axum
filter: Filter, // ?filter[status]=active&filter[role]=admin
}
impl Sanitize for SearchParams {
fn sanitize(&mut self) { self.q = self.q.trim().to_lowercase(); }
}
async fn search(Query(p): Query<SearchParams>) {
// p.filter.status is "active"
}Tuple Fields§
§0: T