mirror of
https://github.com/tokio-rs/axum.git
synced 2026-08-25 00:00:23 +02:00
Percent decode automatically in extract::Path (#272)
* Percent decode automatically in `extract::Path` Fixes https://github.com/tokio-rs/axum/issues/261 * return an error if path param contains invalid utf-8 * Mention automatic decoding in the docs * Update changelog: This is a breaking change * cleanup * fix tests
This commit is contained in:
+34
-9
@@ -9,7 +9,7 @@ use crate::{
|
||||
OriginalUri,
|
||||
},
|
||||
service::HandleError,
|
||||
util::ByteStr,
|
||||
util::{ByteStr, PercentDecodedByteStr},
|
||||
BoxError,
|
||||
};
|
||||
use bytes::Bytes;
|
||||
@@ -627,24 +627,49 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct UrlParams(pub(crate) Vec<(ByteStr, ByteStr)>);
|
||||
// we store the potential error here such that users can handle invalid path
|
||||
// params using `Result<Path<T>, _>`. That wouldn't be possible if we
|
||||
// returned an error immediately when decoding the param
|
||||
pub(crate) struct UrlParams(
|
||||
pub(crate) Result<Vec<(ByteStr, PercentDecodedByteStr)>, InvalidUtf8InPathParam>,
|
||||
);
|
||||
|
||||
fn insert_url_params<B>(req: &mut Request<B>, params: Vec<(String, String)>) {
|
||||
let params = params
|
||||
.into_iter()
|
||||
.map(|(k, v)| (ByteStr::new(k), ByteStr::new(v)));
|
||||
.map(|(k, v)| {
|
||||
if let Some(decoded) = PercentDecodedByteStr::new(v) {
|
||||
Ok((ByteStr::new(k), decoded))
|
||||
} else {
|
||||
Err(InvalidUtf8InPathParam {
|
||||
key: ByteStr::new(k),
|
||||
})
|
||||
}
|
||||
})
|
||||
.collect::<Result<Vec<_>, _>>();
|
||||
|
||||
if let Some(current) = req.extensions_mut().get_mut::<Option<UrlParams>>() {
|
||||
let mut current = current.take().unwrap();
|
||||
current.0.extend(params);
|
||||
req.extensions_mut().insert(Some(current));
|
||||
match params {
|
||||
Ok(params) => {
|
||||
let mut current = current.take().unwrap();
|
||||
if let Ok(current) = &mut current.0 {
|
||||
current.extend(params);
|
||||
}
|
||||
req.extensions_mut().insert(Some(current));
|
||||
}
|
||||
Err(err) => {
|
||||
req.extensions_mut().insert(Some(UrlParams(Err(err))));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
req.extensions_mut()
|
||||
.insert(Some(UrlParams(params.collect())));
|
||||
req.extensions_mut().insert(Some(UrlParams(params)));
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct InvalidUtf8InPathParam {
|
||||
pub(crate) key: ByteStr,
|
||||
}
|
||||
|
||||
/// A [`Service`] that responds with `404 Not Found` or `405 Method not allowed`
|
||||
/// to all requests.
|
||||
///
|
||||
|
||||
Reference in New Issue
Block a user