diff --git a/examples/key_value_store.rs b/examples/key_value_store.rs
index 324b3de4..3bcfc3e3 100644
--- a/examples/key_value_store.rs
+++ b/examples/key_value_store.rs
@@ -52,15 +52,15 @@ struct State {
async fn get(
_req: Request
,
- params: extract::UrlParamsMap,
+ params: extract::UrlParams<(String,)>,
state: extract::Extension,
) -> Result {
let state = state.into_inner();
let db = &state.lock().unwrap().db;
- let key = params.get("key")?;
+ let (key,) = params.into_inner();
- if let Some(value) = db.get(key) {
+ if let Some(value) = db.get(&key) {
Ok(value.clone())
} else {
Err(Error::Status(StatusCode::NOT_FOUND))
@@ -69,14 +69,14 @@ async fn get(
async fn set(
_req: Request,
- params: extract::UrlParamsMap,
+ params: extract::UrlParams<(String,)>,
value: extract::BytesMaxLength<{ 1024 * 5_000 }>, // ~5mb
state: extract::Extension,
) -> Result {
let state = state.into_inner();
let db = &mut state.lock().unwrap().db;
- let key = params.get("key")?;
+ let (key,) = params.into_inner();
let value = value.into_inner();
db.insert(key.to_string(), value);
diff --git a/src/extract.rs b/src/extract.rs
index d1c6b41c..b2270e84 100644
--- a/src/extract.rs
+++ b/src/extract.rs
@@ -197,7 +197,7 @@ impl UrlParamsMap {
pub fn get_typed(&self, key: &str) -> Result
where
- T: std::str::FromStr,
+ T: FromStr,
{
self.get(key)?.parse().map_err(|_| Error::InvalidUrlParam {
type_name: std::any::type_name::(),
@@ -220,3 +220,65 @@ impl FromRequest for UrlParamsMap {
}
}
}
+
+pub struct UrlParams(T);
+
+impl UrlParams {
+ pub fn into_inner(self) -> T {
+ self.0
+ }
+}
+
+macro_rules! impl_parse_url {
+ () => {};
+
+ ( $head:ident, $($tail:ident),* $(,)? ) => {
+ impl<$head, $($tail,)*> FromRequest for UrlParams<($head, $($tail,)*)>
+ where
+ $head: FromStr + Send,
+ $( $tail: FromStr + Send, )*
+ {
+ type Future = future::Ready>;
+
+ #[allow(non_snake_case)]
+ fn from_request(req: &mut Request) -> Self::Future {
+ let params = if let Some(params) = req
+ .extensions_mut()
+ .get_mut::