diff --git a/utoipa/src/openapi/info.rs b/utoipa/src/openapi/info.rs index 967f7ea3..a4b3d5df 100644 --- a/utoipa/src/openapi/info.rs +++ b/utoipa/src/openapi/info.rs @@ -6,6 +6,8 @@ //! [info]: //! [openapi_trait]: ../../trait.OpenApi.html //! [derive]: ../../derive.OpenApi.html +use std::collections::HashMap; + use serde::{Deserialize, Serialize}; use super::{builder, set_value}; @@ -66,6 +68,10 @@ builder! { /// Document version typically the API version. pub version: String, + + /// Optional extensions "x-something" + #[serde(skip_serializing_if = "Option::is_none", flatten)] + pub extensions: Option>, } } @@ -120,6 +126,11 @@ impl InfoBuilder { pub fn license(mut self, license: Option) -> Self { set_value!(self license license) } + + /// Add openapi extensions (x-something) of the API. + pub fn extensions(mut self, extensions: Option>) -> Self { + set_value!(self extensions extensions) + } } builder! { diff --git a/utoipa/src/openapi/path.rs b/utoipa/src/openapi/path.rs index f3a53874..c81acc4f 100644 --- a/utoipa/src/openapi/path.rs +++ b/utoipa/src/openapi/path.rs @@ -1,7 +1,7 @@ //! Implements [OpenAPI Path Object][paths] types. //! //! [paths]: https://spec.openapis.org/oas/latest.html#paths-object -use std::iter; +use std::{collections::HashMap, iter}; use serde::{Deserialize, Serialize}; use serde_json::Value; @@ -34,6 +34,10 @@ builder! { /// Map of relative paths with [`PathItem`]s holding [`Operation`]s matching /// api endpoints. pub paths: PathsMap, + + /// Optional extensions "x-something" + #[serde(skip_serializing_if = "Option::is_none", flatten)] + pub extensions: Option>, } } @@ -97,6 +101,11 @@ impl PathsBuilder { self } + + /// Add extensions to the paths section. + pub fn extensions(mut self, extensions: Option>) -> Self { + set_value!(self extensions extensions) + } } builder! { @@ -135,6 +144,10 @@ builder! { /// per [`PathItemType`]. #[serde(flatten)] pub operations: PathsMap, + + /// Optional extensions "x-something" + #[serde(skip_serializing_if = "Option::is_none", flatten)] + pub extensions: Option>, } } @@ -184,6 +197,11 @@ impl PathItemBuilder { pub fn parameters>(mut self, parameters: Option) -> Self { set_value!(self parameters parameters.map(|parameters| parameters.into_iter().collect())) } + + /// Add openapi extensions (x-something) to this [`PathItem`]. + pub fn extensions(mut self, extensions: Option>) -> Self { + set_value!(self extensions extensions) + } } /// Path item operation type. @@ -295,6 +313,10 @@ builder! { /// Alternative [`Server`]s for this [`Operation`]. #[serde(skip_serializing_if = "Option::is_none")] pub servers: Option>, + + /// Optional extensions "x-something" + #[serde(skip_serializing_if = "Option::is_none", flatten)] + pub extensions: Option>, } } @@ -436,6 +458,11 @@ impl OperationBuilder { self } + + /// Add openapi extensions (x-something) of the [`Operation`]. + pub fn extensions(mut self, extensions: Option>) -> Self { + set_value!(self extensions extensions) + } } builder! { @@ -506,6 +533,10 @@ builder! { /// within [`Parameter::schema`] if defined. #[serde(skip_serializing_if = "Option::is_none")] example: Option, + + /// Optional extensions "x-something" + #[serde(skip_serializing_if = "Option::is_none", flatten)] + pub extensions: Option>, } } @@ -577,6 +608,11 @@ impl ParameterBuilder { pub fn example(mut self, example: Option) -> Self { set_value!(self example example) } + + /// Add openapi extensions (x-something) to the [`Parameter`]. + pub fn extensions(mut self, extensions: Option>) -> Self { + set_value!(self extensions extensions) + } } /// In definition of [`Parameter`]. diff --git a/utoipa/src/openapi/response.rs b/utoipa/src/openapi/response.rs index 9b0f1409..a75eb183 100644 --- a/utoipa/src/openapi/response.rs +++ b/utoipa/src/openapi/response.rs @@ -1,7 +1,7 @@ //! Implements [OpenApi Responses][responses]. //! //! [responses]: https://spec.openapis.org/oas/latest.html#responses-object -use std::collections::BTreeMap; +use std::collections::{BTreeMap, HashMap}; use indexmap::IndexMap; use serde::{Deserialize, Serialize}; @@ -118,6 +118,10 @@ builder! { /// will create and show default example according to the first entry in `content` map. #[serde(skip_serializing_if = "IndexMap::is_empty", default)] pub content: IndexMap, + + /// Optional extensions "x-something" + #[serde(skip_serializing_if = "Option::is_none", flatten)] + pub extensions: Option>, } } @@ -152,6 +156,11 @@ impl ResponseBuilder { self } + + /// Add openapi extensions (x-something) to the [`Header`]. + pub fn extensions(mut self, extensions: Option>) -> Self { + set_value!(self extensions extensions) + } } impl From for RefOr { diff --git a/utoipa/src/openapi/security.rs b/utoipa/src/openapi/security.rs index bb86a0be..f5011d99 100644 --- a/utoipa/src/openapi/security.rs +++ b/utoipa/src/openapi/security.rs @@ -3,7 +3,10 @@ //! Refer to [`SecurityScheme`] for usage and more details. //! //! [security]: https://spec.openapis.org/oas/latest.html#security-scheme-object -use std::{collections::BTreeMap, iter}; +use std::{ + collections::{BTreeMap, HashMap}, + iter, +}; use serde::{Deserialize, Serialize}; @@ -352,6 +355,10 @@ pub struct OAuth2 { /// Optional description for the [`OAuth2`] [`Flow`] [`SecurityScheme`]. #[serde(skip_serializing_if = "Option::is_none")] pub description: Option, + + /// Optional extensions "x-something" + #[serde(skip_serializing_if = "Option::is_none", flatten)] + pub extensions: Option>, } impl OAuth2 { @@ -391,6 +398,7 @@ impl OAuth2 { .into_iter() .map(|auth_flow| (String::from(auth_flow.get_type_as_str()), auth_flow)), ), + extensions: None, description: None, } } @@ -433,6 +441,7 @@ impl OAuth2 { .into_iter() .map(|auth_flow| (String::from(auth_flow.get_type_as_str()), auth_flow)), ), + extensions: None, description: Some(description.into()), } } diff --git a/utoipa/src/openapi/tag.rs b/utoipa/src/openapi/tag.rs index e232801c..d2ee6a8f 100644 --- a/utoipa/src/openapi/tag.rs +++ b/utoipa/src/openapi/tag.rs @@ -1,6 +1,8 @@ //! Implements [OpenAPI Tag Object][tag] types. //! //! [tag]: https://spec.openapis.org/oas/latest.html#tag-object +use std::collections::HashMap; + use serde::{Deserialize, Serialize}; use super::{builder, external_docs::ExternalDocs, set_value}; @@ -28,6 +30,10 @@ builder! { /// Additional external documentation for the tag. #[serde(skip_serializing_if = "Option::is_none")] pub external_docs: Option, + + /// Optional extensions "x-something" + #[serde(skip_serializing_if = "Option::is_none", flatten)] + pub extensions: Option>, } } @@ -56,4 +62,9 @@ impl TagBuilder { pub fn external_docs(mut self, external_docs: Option) -> Self { set_value!(self external_docs external_docs) } + + /// Add openapi extensions (x-something) to the tag. + pub fn extensions(mut self, extensions: Option>) -> Self { + set_value!(self extensions extensions) + } }