diff --git a/core/src/v2/models.rs b/core/src/v2/models.rs index 62d3e4e47..1caea28f6 100644 --- a/core/src/v2/models.rs +++ b/core/src/v2/models.rs @@ -9,6 +9,7 @@ use crate::error::ValidationError; use once_cell::sync::Lazy; use paperclip_macros::api_v2_schema_struct; use regex::{Captures, Regex}; +use serde::ser::{SerializeMap, Serializer}; #[cfg(feature = "actix-base")] use actix_web::http::Method; @@ -135,6 +136,36 @@ pub type ResolvableApi = Api, ResolvableResponse, R /// OpenAPI v2 spec with defaults. pub type DefaultApiRaw = Api; +fn strip_templates_from_paths( + tree: &BTreeMap>, + serializer: S, +) -> Result { + let len = tree.len(); + let mut map = serializer.serialize_map(Some(len))?; + for (k, v) in tree { + let path = strip_pattern_from_template(k); + map.serialize_entry(&path, v)?; + } + map.end() +} + +fn strip_pattern_from_template(path: &str) -> String { + let mut clean_path = path.to_string(); + for cap in PATH_TEMPLATE_REGEX.captures_iter(path) { + let name_only = cap[1] + .split_once(':') + .map(|t| t.0.to_string()) + .unwrap_or_else(|| cap[1].to_string()); + if cap[1] != name_only { + clean_path = clean_path.replace( + format!("{{{}}}", &cap[1]).as_str(), + format!("{{{}}}", name_only).as_str(), + ); + } + } + clean_path +} + /// OpenAPI v2 (swagger) spec generic over parameter and schema. /// /// @@ -143,6 +174,7 @@ pub struct Api { pub swagger: Version, #[serde(default = "BTreeMap::new")] pub definitions: BTreeMap, + #[serde(serialize_with = "strip_templates_from_paths")] pub paths: BTreeMap>, #[serde(skip_serializing_if = "Option::is_none")] pub host: Option, @@ -706,7 +738,12 @@ impl Operation, Response> { .rev() { if let Some(n) = names.pop() { - p.name = n.split_once(':').map(|t| t.0.to_string()).unwrap_or(n); + if let Some((name, pattern)) = n.split_once(':') { + p.name = name.to_string(); + p.pattern = Some(pattern.to_string()); + } else { + p.name = n; + } } else { break; }