Support extracting URL params multiple times (#15)

Useful when building higher order extractors.
This commit is contained in:
David Pedersen
2021-06-13 13:06:33 +02:00
committed by GitHub
parent 2b360a7873
commit c41c9e0f78
6 changed files with 69 additions and 36 deletions
+13 -13
View File
@@ -165,7 +165,7 @@
//! # };
//! ```
use crate::{body::Body, response::IntoResponse};
use crate::{body::Body, response::IntoResponse, util::ByteStr};
use async_trait::async_trait;
use bytes::{Buf, Bytes};
use http::{header, HeaderMap, Method, Request, Uri, Version};
@@ -609,12 +609,12 @@ where
/// Note that you can only have one URL params extractor per handler. If you
/// have multiple it'll response with `500 Internal Server Error`.
#[derive(Debug)]
pub struct UrlParamsMap(HashMap<String, String>);
pub struct UrlParamsMap(HashMap<ByteStr, ByteStr>);
impl UrlParamsMap {
/// Look up the value for a key.
pub fn get(&self, key: &str) -> Option<&str> {
self.0.get(key).map(|s| &**s)
self.0.get(&ByteStr::new(key)).map(|s| s.as_str())
}
/// Look up the value for a key and parse it into a value of type `T`.
@@ -628,20 +628,20 @@ impl UrlParamsMap {
#[async_trait]
impl FromRequest for UrlParamsMap {
type Rejection = UrlParamsMapRejection;
type Rejection = MissingRouteParams;
async fn from_request(req: &mut Request<Body>) -> Result<Self, Self::Rejection> {
if let Some(params) = req
.extensions_mut()
.get_mut::<Option<crate::routing::UrlParams>>()
{
if let Some(params) = params.take() {
Ok(Self(params.0.into_iter().collect()))
if let Some(params) = params {
Ok(Self(params.0.iter().cloned().collect()))
} else {
Err(UrlParamsAlreadyExtracted.into())
Ok(Self(Default::default()))
}
} else {
Err(MissingRouteParams.into())
Err(MissingRouteParams)
}
}
}
@@ -689,24 +689,24 @@ macro_rules! impl_parse_url {
.extensions_mut()
.get_mut::<Option<crate::routing::UrlParams>>()
{
if let Some(params) = params.take() {
params.0
if let Some(params) = params {
params.0.clone()
} else {
return Err(UrlParamsAlreadyExtracted.into());
Default::default()
}
} else {
return Err(MissingRouteParams.into())
};
if let [(_, $head), $((_, $tail),)*] = &*params {
let $head = if let Ok(x) = $head.parse::<$head>() {
let $head = if let Ok(x) = $head.as_str().parse::<$head>() {
x
} else {
return Err(InvalidUrlParam::new::<$head>().into());
};
$(
let $tail = if let Ok(x) = $tail.parse::<$tail>() {
let $tail = if let Ok(x) = $tail.as_str().parse::<$tail>() {
x
} else {
return Err(InvalidUrlParam::new::<$tail>().into());
-19
View File
@@ -127,13 +127,6 @@ define_rejection! {
pub struct MissingRouteParams;
}
define_rejection! {
#[status = INTERNAL_SERVER_ERROR]
#[body = "Cannot have two URL capture extractors for a single handler"]
/// Rejection type used if you try and extract the URL params more than once.
pub struct UrlParamsAlreadyExtracted;
}
define_rejection! {
#[status = INTERNAL_SERVER_ERROR]
#[body = "Cannot have two request body extractors for a single handler"]
@@ -288,17 +281,6 @@ composite_rejection! {
}
}
composite_rejection! {
/// Rejection used for [`UrlParamsMap`](super::UrlParamsMap).
///
/// Contains one variant for each way the [`UrlParamsMap`](super::UrlParamsMap) extractor
/// can fail.
pub enum UrlParamsMapRejection {
UrlParamsAlreadyExtracted,
MissingRouteParams,
}
}
composite_rejection! {
/// Rejection used for [`UrlParams`](super::UrlParams).
///
@@ -306,7 +288,6 @@ composite_rejection! {
/// can fail.
pub enum UrlParamsRejection {
InvalidUrlParam,
UrlParamsAlreadyExtracted,
MissingRouteParams,
}
}