diff --git a/poem-openapi/src/openapi.rs b/poem-openapi/src/openapi.rs index a9a3d354a1..96c795a62a 100644 --- a/poem-openapi/src/openapi.rs +++ b/poem-openapi/src/openapi.rs @@ -221,6 +221,7 @@ pub struct OpenApiService { cookie_key: Option, extra_response_headers: Vec<(ExtraHeader, MetaSchemaRef, bool)>, extra_request_headers: Vec<(ExtraHeader, MetaSchemaRef, bool)>, + url_prefix: Option, } impl OpenApiService { @@ -244,6 +245,7 @@ impl OpenApiService { cookie_key: None, extra_response_headers: vec![], extra_request_headers: vec![], + url_prefix: None, } } } @@ -260,6 +262,7 @@ impl OpenApiService { cookie_key: self.cookie_key, extra_response_headers: self.extra_response_headers, extra_request_headers: self.extra_request_headers, + url_prefix: None, } } @@ -373,6 +376,14 @@ impl OpenApiService { } } + /// Sets optional URl prefix to be added to path + pub fn url_prefix(self, url_prefix: impl Into) -> Self { + Self { + url_prefix: Some(url_prefix.into()), + ..self + } + } + /// Create the OpenAPI Explorer endpoint. #[must_use] #[cfg(feature = "openapi-explorer")] @@ -554,6 +565,7 @@ impl OpenApiService { webhooks, registry, external_document: self.external_document.as_ref(), + url_prefix: self.url_prefix.as_deref(), }; doc.remove_unused_schemas(); diff --git a/poem-openapi/src/registry/ser.rs b/poem-openapi/src/registry/ser.rs index d661612020..5148df1bca 100644 --- a/poem-openapi/src/registry/ser.rs +++ b/poem-openapi/src/registry/ser.rs @@ -22,14 +22,17 @@ impl Serialize for MetaSchemaRef { } } -struct PathMap<'a>(&'a [MetaApi]); +struct PathMap<'a>(&'a [MetaApi], Option<&'a str>); impl<'a> Serialize for PathMap<'a> { fn serialize(&self, serializer: S) -> Result { let mut s = serializer.serialize_map(Some(self.0.len()))?; for api in self.0 { for path in &api.paths { - s.serialize_entry(path.path, path)?; + match self.1 { + Some(p) => s.serialize_entry(&format!("{}{}", p, path.path), path)?, + None => s.serialize_entry(path.path, path)?, + } } } s.end() @@ -80,6 +83,7 @@ pub(crate) struct Document<'a> { pub(crate) webhooks: Vec, pub(crate) registry: Registry, pub(crate) external_document: Option<&'a MetaExternalDocument>, + pub(crate) url_prefix: Option<&'a str>, } impl<'a> Serialize for Document<'a> { @@ -101,7 +105,7 @@ impl<'a> Serialize for Document<'a> { if !self.webhooks.is_empty() { s.serialize_entry("webhooks", &WebhookMap(&self.webhooks))?; } - s.serialize_entry("paths", &PathMap(&self.apis))?; + s.serialize_entry("paths", &PathMap(&self.apis, self.url_prefix))?; s.serialize_entry( "components", &Components {