diff --git a/gotham_restful/src/lib.rs b/gotham_restful/src/lib.rs
index 1cc9420..f78109a 100644
--- a/gotham_restful/src/lib.rs
+++ b/gotham_restful/src/lib.rs
@@ -151,7 +151,7 @@ pub use auth::{
mod openapi;
#[cfg(feature = "openapi")]
pub use openapi::{
- router::{GetOpenapi, OpenapiRouter},
+ router::GetOpenapi,
types::{OpenapiSchema, OpenapiType}
};
diff --git a/gotham_restful/src/openapi/router.rs b/gotham_restful/src/openapi/router.rs
index 9f5c185..6e9be42 100644
--- a/gotham_restful/src/openapi/router.rs
+++ b/gotham_restful/src/openapi/router.rs
@@ -12,8 +12,14 @@ use gotham::{
extractor::QueryStringExtractor,
handler::{Handler, HandlerFuture, NewHandler},
helpers::http::response::create_response,
- pipeline::chain::PipelineHandleChain,
- router::builder::*,
+ pipeline::{
+ chain::PipelineHandleChain,
+ set::PipelineSet
+ },
+ router::{
+ builder::*,
+ tree::node::Node
+ },
state::State
};
use hyper::Body;
@@ -28,15 +34,10 @@ use openapiv3::{
use serde::de::DeserializeOwned;
use std::panic::RefUnwindSafe;
-/**
-This type is required to build routes while adding them to the generated OpenAPI Spec at the
-same time. There is no need to use this type directly. See [`WithOpenapi`] on how to do this.
+/// A helper struct for `OpenapiRouter` to build the OpenAPI specification.
+pub struct OpenapiBuilder(OpenAPI);
-[`WithOpenapi`]: trait.WithOpenapi.html
-*/
-pub struct OpenapiRouter(OpenAPI);
-
-impl OpenapiRouter
+impl OpenapiBuilder
{
pub fn new
(title : Title, version : Version, server_url : Url) -> Self
{
@@ -129,7 +130,7 @@ struct OpenapiHandler(OpenAPI);
impl OpenapiHandler
{
- fn new(openapi : &OpenapiRouter) -> Self
+ fn new(openapi : &OpenapiBuilder) -> Self
{
Self(openapi.0.clone())
}
@@ -365,173 +366,259 @@ fn new_operation(
}
}
-macro_rules! implOpenapiRouter {
- ($implType:ident) => {
+struct OpenapiRouteBuilder<'a, C, P>
+where
+ C : PipelineHandleChain + Copy + Send + Sync + 'static,
+ P : Send + Sync + 'static
+{
+ node_builder : &'a mut Node,
+ pipeline_chain : C,
+ pipelines : PipelineSet
+}
- impl<'a, C, P> GetOpenapi for (&mut $implType<'a, C, P>, &mut OpenapiRouter)
- where
- C : PipelineHandleChain
+ Copy + Send + Sync + 'static,
- P : RefUnwindSafe + Send + Sync + 'static
- {
- fn get_openapi(&mut self, path : &str)
- {
- self.0.get(path).to_new_handler(OpenapiHandler::new(&self.1));
- }
+impl<'a, C, P> OpenapiRouteBuilder<'a, C, P>
+where
+ C : PipelineHandleChain
+ Copy + Send + Sync + 'static,
+ P : RefUnwindSafe + Send + Sync + 'static
+{
+ fn new(router : &'a mut D) -> Self
+ where
+ D : DrawRoutes + 'a
+ {
+ let (node_builder, pipeline_chain, pipelines) = router.component_refs();
+ Self {
+ node_builder,
+ pipeline_chain: *pipeline_chain,
+ pipelines: pipelines.clone()
}
-
- impl<'a, C, P> DrawResources for (&mut $implType<'a, C, P>, &mut OpenapiRouter)
- where
- C : PipelineHandleChain + Copy + Send + Sync + 'static,
- P : RefUnwindSafe + Send + Sync + 'static
- {
- fn resource(&mut self, path : T)
- {
- R::setup((self, path.to_string()));
- }
- }
-
- impl<'a, C, P> DrawResourceRoutes for (&mut (&mut $implType<'a, C, P>, &mut OpenapiRouter), String)
- where
- C : PipelineHandleChain + Copy + Send + Sync + 'static,
- P : RefUnwindSafe + Send + Sync + 'static
- {
- fn read_all(&mut self)
- where
- Res : ResourceResult,
- Handler : ResourceReadAll
- {
- let schema = (self.0).1.add_schema::();
-
- let path = format!("/{}", &self.1);
- let mut item = (self.0).1.remove_path(&path);
- item.get = Some(new_operation(Res::default_status(), Res::accepted_types(), schema, OperationParams::default(), None, None, Res::requires_auth()));
- (self.0).1.add_path(path, item);
-
- (&mut *(self.0).0, self.1.to_string()).read_all::()
- }
-
- fn read(&mut self)
- where
- ID : DeserializeOwned + Clone + RefUnwindSafe + Send + Sync + 'static,
- Res : ResourceResult,
- Handler : ResourceRead
- {
- let schema = (self.0).1.add_schema::();
-
- let path = format!("/{}/{{id}}", &self.1);
- let mut item = (self.0).1.remove_path(&path);
- item.get = Some(new_operation(Res::default_status(), Res::accepted_types(), schema, OperationParams::from_path_params(vec!["id"]), None, None, Res::requires_auth()));
- (self.0).1.add_path(path, item);
-
- (&mut *(self.0).0, self.1.to_string()).read::()
- }
-
- fn search(&mut self)
- where
- Query : ResourceType + DeserializeOwned + QueryStringExtractor + Send + Sync + 'static,
- Res : ResourceResult,
- Handler : ResourceSearch
- {
- let schema = (self.0).1.add_schema::();
-
- let path = format!("/{}/search", &self.1);
- let mut item = (self.0).1.remove_path(&self.1);
- item.get = Some(new_operation(Res::default_status(), Res::accepted_types(), schema, OperationParams::from_query_params(Query::schema()), None, None, Res::requires_auth()));
- (self.0).1.add_path(path, item);
-
- (&mut *(self.0).0, self.1.to_string()).search::()
- }
-
- fn create(&mut self)
- where
- Body : RequestBody,
- Res : ResourceResult,
- Handler : ResourceCreate
- {
- let schema = (self.0).1.add_schema::();
- let body_schema = (self.0).1.add_schema::();
-
- let path = format!("/{}", &self.1);
- let mut item = (self.0).1.remove_path(&path);
- item.post = Some(new_operation(Res::default_status(), Res::accepted_types(), schema, OperationParams::default(), Some(body_schema), Body::supported_types(), Res::requires_auth()));
- (self.0).1.add_path(path, item);
-
- (&mut *(self.0).0, self.1.to_string()).create::()
- }
-
- fn update_all(&mut self)
- where
- Body : RequestBody,
- Res : ResourceResult,
- Handler : ResourceUpdateAll
- {
- let schema = (self.0).1.add_schema::();
- let body_schema = (self.0).1.add_schema::();
-
- let path = format!("/{}", &self.1);
- let mut item = (self.0).1.remove_path(&path);
- item.put = Some(new_operation(Res::default_status(), Res::accepted_types(), schema, OperationParams::default(), Some(body_schema), Body::supported_types(), Res::requires_auth()));
- (self.0).1.add_path(path, item);
-
- (&mut *(self.0).0, self.1.to_string()).update_all::()
- }
-
- fn update(&mut self)
- where
- ID : DeserializeOwned + Clone + RefUnwindSafe + Send + Sync + 'static,
- Body : RequestBody,
- Res : ResourceResult,
- Handler : ResourceUpdate
- {
- let schema = (self.0).1.add_schema::();
- let body_schema = (self.0).1.add_schema::();
-
- let path = format!("/{}/{{id}}", &self.1);
- let mut item = (self.0).1.remove_path(&path);
- item.put = Some(new_operation(Res::default_status(), Res::accepted_types(), schema, OperationParams::from_path_params(vec!["id"]), Some(body_schema), Body::supported_types(), Res::requires_auth()));
- (self.0).1.add_path(path, item);
-
- (&mut *(self.0).0, self.1.to_string()).update::()
- }
-
- fn delete_all(&mut self)
- where
- Res : ResourceResult,
- Handler : ResourceDeleteAll
- {
- let schema = (self.0).1.add_schema::();
-
- let path = format!("/{}", &self.1);
- let mut item = (self.0).1.remove_path(&path);
- item.delete = Some(new_operation(Res::default_status(), Res::accepted_types(), schema, OperationParams::default(), None, None, Res::requires_auth()));
- (self.0).1.add_path(path, item);
-
- (&mut *(self.0).0, self.1.to_string()).delete_all::()
- }
-
- fn delete(&mut self)
- where
- ID : DeserializeOwned + Clone + RefUnwindSafe + Send + Sync + 'static,
- Res : ResourceResult,
- Handler : ResourceDelete
- {
- let schema = (self.0).1.add_schema::();
-
- let path = format!("/{}/{{id}}", &self.1);
- let mut item = (self.0).1.remove_path(&path);
- item.delete = Some(new_operation(Res::default_status(), Res::accepted_types(), schema, OperationParams::from_path_params(vec!["id"]), None, None, Res::requires_auth()));
- (self.0).1.add_path(path, item);
-
- (&mut *(self.0).0, self.1.to_string()).delete::()
- }
- }
-
}
}
-implOpenapiRouter!(RouterBuilder);
-implOpenapiRouter!(ScopeBuilder);
+impl<'a, C, P> DrawRoutes for OpenapiRouteBuilder<'a, C, P>
+where
+ C : PipelineHandleChain + Copy + Send + Sync + 'static,
+ P : RefUnwindSafe + Send + Sync + 'static
+{
+ fn component_refs(&mut self) -> (&mut Node, &mut C, &PipelineSet
)
+ {
+ (&mut self.node_builder, &mut self.pipeline_chain, &self.pipelines)
+ }
+}
+/**
+This type is required to build routes while adding them to the generated OpenAPI Spec at the
+same time. There is no need to use this type directly. See [`WithOpenapi`] on how to do this.
+
+[`WithOpenapi`]: trait.WithOpenapi.html
+*/
+pub struct OpenapiRouter<'a, C, P>
+where
+ C : PipelineHandleChain
+ Copy + Send + Sync + 'static,
+ P : Send + Sync + 'static
+{
+ builder : OpenapiRouteBuilder<'a, C, P>,
+ openapi : OpenapiBuilder
+}
+
+impl<'a, C, P> OpenapiRouter<'a, C, P>
+where
+ C : PipelineHandleChain
+ Copy + Send + Sync + 'static,
+ P : RefUnwindSafe + Send + Sync + 'static
+{
+ pub fn new(router : &'a mut D, openapi : OpenapiBuilder) -> Self
+ where
+ D : DrawRoutes
+ {
+ Self {
+ builder: OpenapiRouteBuilder::new(router),
+ openapi
+ }
+ }
+}
+
+impl<'a, C, P> GetOpenapi for OpenapiRouter<'a, C, P>
+where
+ C : PipelineHandleChain + Copy + Send + Sync + 'static,
+ P : RefUnwindSafe + Send + Sync + 'static
+{
+ fn get_openapi(&mut self, path : &str)
+ {
+ self.builder.get(path).to_new_handler(OpenapiHandler::new(&self.openapi));
+ }
+}
+
+impl<'a, C, P> DrawResources for OpenapiRouter<'a, C, P>
+where
+ C : PipelineHandleChain + Copy + Send + Sync + 'static,
+ P : RefUnwindSafe + Send + Sync + 'static
+{
+ fn resource<'b, R : Resource>(&'b mut self, path : &'b str)
+ {
+ R::setup(OpenapiResourceSetup::new(self, path));
+ }
+}
+
+struct OpenapiResourceSetup<'a, C, P>
+where
+ C : PipelineHandleChain
+ Copy + Send + Sync + 'static,
+ P : Send + Sync + 'static
+{
+ builder : OpenapiRouteBuilder<'a, C, P>,
+ openapi : &'a mut OpenapiBuilder,
+ path : &'a str
+}
+
+impl<'a, C, P> OpenapiResourceSetup<'a, C, P>
+where
+ C : PipelineHandleChain
+ Copy + Send + Sync + 'static,
+ P : Send + Sync + 'static
+{
+ fn new(router : &'a mut OpenapiRouter<'a, C, P>, path : &'a str) -> Self
+ {
+ Self {
+ builder: &mut router.builder,
+ openapi: &mut router.openapi,
+ path
+ }
+ }
+}
+
+/*
+impl<'a, C, P> DrawResourceRoutes for OpenapiResourceSetup<'a, C, P>
+where
+ C : PipelineHandleChain
+ Copy + Send + Sync + 'static,
+ P : RefUnwindSafe + Send + Sync + 'static
+{
+ fn read_all(&mut self)
+ where
+ Res : ResourceResult,
+ Handler : ResourceReadAll
+ {
+ let schema = (self.0).1.add_schema::();
+
+ let path = format!("/{}", &self.1);
+ let mut item = (self.0).1.remove_path(&path);
+ item.get = Some(new_operation(Res::default_status(), Res::accepted_types(), schema, OperationParams::default(), None, None, Res::requires_auth()));
+ (self.0).1.add_path(path, item);
+
+ (&mut *(self.0).0, self.1.to_string()).read_all::()
+ }
+
+ fn read(&mut self)
+ where
+ ID : DeserializeOwned + Clone + RefUnwindSafe + Send + Sync + 'static,
+ Res : ResourceResult,
+ Handler : ResourceRead
+ {
+ let schema = (self.0).1.add_schema::();
+
+ let path = format!("/{}/{{id}}", &self.1);
+ let mut item = (self.0).1.remove_path(&path);
+ item.get = Some(new_operation(Res::default_status(), Res::accepted_types(), schema, OperationParams::from_path_params(vec!["id"]), None, None, Res::requires_auth()));
+ (self.0).1.add_path(path, item);
+
+ (&mut *(self.0).0, self.1.to_string()).read::()
+ }
+
+ fn search(&mut self)
+ where
+ Query : ResourceType + DeserializeOwned + QueryStringExtractor + Send + Sync + 'static,
+ Res : ResourceResult,
+ Handler : ResourceSearch
+ {
+ let schema = (self.0).1.add_schema::();
+
+ let path = format!("/{}/search", &self.1);
+ let mut item = (self.0).1.remove_path(&self.1);
+ item.get = Some(new_operation(Res::default_status(), Res::accepted_types(), schema, OperationParams::from_query_params(Query::schema()), None, None, Res::requires_auth()));
+ (self.0).1.add_path(path, item);
+
+ (&mut *(self.0).0, self.1.to_string()).search::()
+ }
+
+ fn create(&mut self)
+ where
+ Body : RequestBody,
+ Res : ResourceResult,
+ Handler : ResourceCreate
+ {
+ let schema = (self.0).1.add_schema::();
+ let body_schema = (self.0).1.add_schema::();
+
+ let path = format!("/{}", &self.1);
+ let mut item = (self.0).1.remove_path(&path);
+ item.post = Some(new_operation(Res::default_status(), Res::accepted_types(), schema, OperationParams::default(), Some(body_schema), Body::supported_types(), Res::requires_auth()));
+ (self.0).1.add_path(path, item);
+
+ (&mut *(self.0).0, self.1.to_string()).create::()
+ }
+
+ fn update_all(&mut self)
+ where
+ Body : RequestBody,
+ Res : ResourceResult,
+ Handler : ResourceUpdateAll
+ {
+ let schema = (self.0).1.add_schema::();
+ let body_schema = (self.0).1.add_schema::();
+
+ let path = format!("/{}", &self.1);
+ let mut item = (self.0).1.remove_path(&path);
+ item.put = Some(new_operation(Res::default_status(), Res::accepted_types(), schema, OperationParams::default(), Some(body_schema), Body::supported_types(), Res::requires_auth()));
+ (self.0).1.add_path(path, item);
+
+ (&mut *(self.0).0, self.1.to_string()).update_all::()
+ }
+
+ fn update(&mut self)
+ where
+ ID : DeserializeOwned + Clone + RefUnwindSafe + Send + Sync + 'static,
+ Body : RequestBody,
+ Res : ResourceResult,
+ Handler : ResourceUpdate
+ {
+ let schema = (self.0).1.add_schema::();
+ let body_schema = (self.0).1.add_schema::();
+
+ let path = format!("/{}/{{id}}", &self.1);
+ let mut item = (self.0).1.remove_path(&path);
+ item.put = Some(new_operation(Res::default_status(), Res::accepted_types(), schema, OperationParams::from_path_params(vec!["id"]), Some(body_schema), Body::supported_types(), Res::requires_auth()));
+ (self.0).1.add_path(path, item);
+
+ (&mut *(self.0).0, self.1.to_string()).update::()
+ }
+
+ fn delete_all(&mut self)
+ where
+ Res : ResourceResult,
+ Handler : ResourceDeleteAll
+ {
+ let schema = (self.0).1.add_schema::();
+
+ let path = format!("/{}", &self.1);
+ let mut item = (self.0).1.remove_path(&path);
+ item.delete = Some(new_operation(Res::default_status(), Res::accepted_types(), schema, OperationParams::default(), None, None, Res::requires_auth()));
+ (self.0).1.add_path(path, item);
+
+ (&mut *(self.0).0, self.1.to_string()).delete_all::()
+ }
+
+ fn delete(&mut self)
+ where
+ ID : DeserializeOwned + Clone + RefUnwindSafe + Send + Sync + 'static,
+ Res : ResourceResult,
+ Handler : ResourceDelete
+ {
+ let schema = (self.0).1.add_schema::();
+
+ let path = format!("/{}/{{id}}", &self.1);
+ let mut item = (self.0).1.remove_path(&path);
+ item.delete = Some(new_operation(Res::default_status(), Res::accepted_types(), schema, OperationParams::from_path_params(vec!["id"]), None, None, Res::requires_auth()));
+ (self.0).1.add_path(path, item);
+
+ (&mut *(self.0).0, self.1.to_string()).delete::()
+ }
+}
#[cfg(test)]
mod test
@@ -603,3 +690,4 @@ mod test
assert_eq!(json, r#"{"schema":{"type":"string","format":"binary"}}"#);
}
}
+*/
\ No newline at end of file
diff --git a/gotham_restful/src/routing.rs b/gotham_restful/src/routing.rs
index 5bd2b1d..61c8c97 100644
--- a/gotham_restful/src/routing.rs
+++ b/gotham_restful/src/routing.rs
@@ -6,7 +6,7 @@ use crate::{
StatusCode
};
#[cfg(feature = "openapi")]
-use crate::OpenapiRouter;
+use crate::openapi::router::{OpenapiBuilder, OpenapiRouter};
use futures::{
future::{Future, err, ok},
@@ -60,7 +60,7 @@ where
{
fn with_openapi(&mut self, title : Title, version : Version, server_url : Url, block : F)
where
- F : FnOnce((&mut D, &mut OpenapiRouter)),
+ F : FnOnce(OpenapiRouter),
Title : ToString,
Version : ToString,
Url : ToString;
@@ -355,13 +355,13 @@ where
{
fn with_openapi(&mut self, title : Title, version : Version, server_url : Url, block : F)
where
- F : FnOnce((&mut Self, &mut OpenapiRouter)),
+ F : FnOnce(OpenapiRouter),
Title : ToString,
Version : ToString,
Url : ToString
{
- let mut router = OpenapiRouter::new(title, version, server_url);
- block((self, &mut router));
+ let router = OpenapiRouter::new(self, OpenapiBuilder::new(title, version, server_url));
+ block(router);
}
}