axum/routing/
url_params.rs
1use crate::util::PercentDecodedStr;
2use http::Extensions;
3use matchit::Params;
4use std::sync::Arc;
5
6#[derive(Clone)]
7pub(crate) enum UrlParams {
8 Params(Vec<(Arc<str>, PercentDecodedStr)>),
9 InvalidUtf8InPathParam { key: Arc<str> },
10}
11
12pub(super) fn insert_url_params(extensions: &mut Extensions, params: Params) {
13 let current_params = extensions.get_mut();
14
15 if let Some(UrlParams::InvalidUtf8InPathParam { .. }) = current_params {
16 return;
18 }
19
20 let params = params
21 .iter()
22 .filter(|(key, _)| !key.starts_with(super::NEST_TAIL_PARAM))
23 .filter(|(key, _)| !key.starts_with(super::FALLBACK_PARAM))
24 .map(|(k, v)| {
25 if let Some(decoded) = PercentDecodedStr::new(v) {
26 Ok((Arc::from(k), decoded))
27 } else {
28 Err(Arc::from(k))
29 }
30 })
31 .collect::<Result<Vec<_>, _>>();
32
33 match (current_params, params) {
34 (Some(UrlParams::InvalidUtf8InPathParam { .. }), _) => {
35 unreachable!("we check for this state earlier in this method")
36 }
37 (_, Err(invalid_key)) => {
38 extensions.insert(UrlParams::InvalidUtf8InPathParam { key: invalid_key });
39 }
40 (Some(UrlParams::Params(current)), Ok(params)) => {
41 current.extend(params);
42 }
43 (None, Ok(params)) => {
44 extensions.insert(UrlParams::Params(params));
45 }
46 }
47}