From 5f3964d560df2047a8a6037f616bf928d2ec6f4c Mon Sep 17 00:00:00 2001 From: Mike Bush Date: Fri, 27 Nov 2020 09:30:15 +0000 Subject: [PATCH] Transform api operations based upon middleware wrappers --- plugins/actix-web/src/web.rs | 48 +++++++++++++++++++++++++++--------- src/build/build.rs | 2 +- 2 files changed, 37 insertions(+), 13 deletions(-) diff --git a/plugins/actix-web/src/web.rs b/plugins/actix-web/src/web.rs index 7c10e55585..bba40ab78a 100644 --- a/plugins/actix-web/src/web.rs +++ b/plugins/actix-web/src/web.rs @@ -35,12 +35,13 @@ const METHODS: &[Method] = &[ /* Resource */ /// Wrapper for [`actix_web::Resource`](https://docs.rs/actix-web/*/actix_web/struct.Resource.html) -pub struct Resource { +pub struct Resource { path: String, operations: BTreeMap, definitions: BTreeMap, security: BTreeMap, inner: R, + api_transformations: N, } impl Resource { @@ -52,11 +53,12 @@ impl Resource { definitions: BTreeMap::new(), security: BTreeMap::new(), inner: actix_web::Resource::new(path), + api_transformations: (), } } } -impl HttpServiceFactory for Resource> +impl HttpServiceFactory for Resource, N> where T: ServiceFactory< Config = (), @@ -86,7 +88,7 @@ where } } -impl Mountable for Resource { +impl Mountable for Resource { fn path(&self) -> &str { &self.path } @@ -104,7 +106,7 @@ impl Mountable for Resource { } } -impl Resource> +impl Resource, N> where T: ServiceFactory< Config = (), @@ -113,6 +115,7 @@ where Error = Error, InitError = (), >, + N: TransformApi, { /// Proxy for [`actix_web::Resource::name`](https://docs.rs/actix-web/*/actix_web/struct.Resource.html#method.name). /// @@ -132,7 +135,7 @@ where /// Wrapper for [`actix_web::Resource::route`](https://docs.rs/actix-web/*/actix_web/struct.Resource.html#method.route). pub fn route(mut self, route: Route) -> Self { - let w = RouteWrapper::from(&self.path, route); + let w = self.api_transformations.transform(RouteWrapper::from(&self.path, route)); self.operations.extend(w.operations.into_iter()); self.definitions.extend(w.definitions.into_iter()); SecurityScheme::append_map(w.security, &mut self.security); @@ -172,7 +175,7 @@ where /// Proxy for [`actix_web::web::Resource::wrap`](https://docs.rs/actix-web/*/actix_web/struct.Resource.html#method.wrap). /// - /// **NOTE:** This doesn't affect spec generation. + /// The proxy adds to the signature of `wrap`'s actix-web `Transform` type that `paperclip::actix::web::TransformApi` is implemented. It can be used to transform the spec operations based on this middleware. pub fn wrap( self, mw: M, @@ -186,6 +189,7 @@ where InitError = (), >, >, + (N, M), > where M: Transform< @@ -194,14 +198,15 @@ where Response = ServiceResponse, Error = Error, InitError = (), - >, + > + TransformApi + Clone, { Resource { path: self.path, operations: self.operations, definitions: self.definitions, security: self.security, - inner: self.inner.wrap(mw), + inner: self.inner.wrap(mw.clone()), + api_transformations: (self.api_transformations, mw), } } @@ -221,6 +226,7 @@ where InitError = (), >, >, + N, > where F: FnMut(ServiceRequest, &mut T::Service) -> R + Clone, @@ -232,6 +238,7 @@ where definitions: self.definitions, security: self.security, inner: self.inner.wrap_fn(mw), + api_transformations: self.api_transformations, } } @@ -627,11 +634,11 @@ pub fn head() -> Route { /// us to call the `.route` method on that entity rather than creating a resource with a /// route. This wrapper is `Mountable` and can be used by `App`, `Scope`, etc. when calling /// the `.route()` method. -pub(crate) struct RouteWrapper { +pub struct RouteWrapper { path: S, - pub(crate) operations: BTreeMap, - pub(crate) definitions: BTreeMap, - pub(crate) security: BTreeMap, + pub operations: BTreeMap, + pub definitions: BTreeMap, + pub security: BTreeMap, pub(crate) inner: actix_web::Route, } @@ -684,6 +691,23 @@ where } } +pub trait TransformApi { + /// Perform a transformation on the api operations of the route based on the properties of this middleware + fn transform(&self, route: RouteWrapper) -> RouteWrapper { + route + } +} + +impl TransformApi for () {} + +impl TransformApi for (N, M) +where N: TransformApi, + M: TransformApi { + fn transform(&self, route: RouteWrapper) -> RouteWrapper { + self.1.transform(self.0.transform(route)) + } +} + /* Service config */ /// Wrapper for [`actix_web::web::ServiceConfig`](https://docs.rs/actix-web/*/actix_web/web/struct.ServiceConfig.html). diff --git a/src/build/build.rs b/src/build/build.rs index 833ced5ce6..ab897da063 100644 --- a/src/build/build.rs +++ b/src/build/build.rs @@ -39,7 +39,7 @@ mod template { ", ); contents.push_str(&name); - contents.push_str(","); + contents.push(','); } contents.push_str(