mirror of
https://gitlab.com/msrd0/gotham-restful.git
synced 2025-02-22 20:52:27 +00:00
support scopes inside openapi router (implements #5)
This commit is contained in:
parent
022edede62
commit
e7e55514a2
5 changed files with 99 additions and 14 deletions
|
@ -12,7 +12,7 @@ test-default:
|
|||
before_script:
|
||||
- cargo -V
|
||||
script:
|
||||
- cargo test --workspace --lib
|
||||
- cargo test --workspace --tests
|
||||
cache:
|
||||
paths:
|
||||
- cargo/
|
||||
|
|
|
@ -14,7 +14,7 @@ pub struct OpenapiInfo
|
|||
pub urls : Vec<String>
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct OpenapiBuilder
|
||||
{
|
||||
pub openapi : Arc<RwLock<OpenAPI>>
|
||||
|
|
|
@ -19,13 +19,36 @@ pub trait GetOpenapi
|
|||
#[derive(Debug)]
|
||||
pub struct OpenapiRouter<'a, D>
|
||||
{
|
||||
pub router : &'a mut D,
|
||||
pub openapi_builder : &'a mut OpenapiBuilder
|
||||
pub(crate) router : &'a mut D,
|
||||
pub(crate) scope : Option<&'a str>,
|
||||
pub(crate) openapi_builder : &'a mut OpenapiBuilder
|
||||
}
|
||||
|
||||
macro_rules! implOpenapiRouter {
|
||||
($implType:ident) => {
|
||||
|
||||
|
||||
impl<'a, 'b, C, P> OpenapiRouter<'a, $implType<'b, C, P>>
|
||||
where
|
||||
C : PipelineHandleChain<P> + Copy + Send + Sync + 'static,
|
||||
P : RefUnwindSafe + Send + Sync + 'static
|
||||
{
|
||||
pub fn scope<F>(&mut self, path : &str, callback : F)
|
||||
where
|
||||
F : FnOnce(&mut OpenapiRouter<'_, ScopeBuilder<'_, C, P>>)
|
||||
{
|
||||
let mut openapi_builder = self.openapi_builder.clone();
|
||||
let new_scope = self.scope.map(|scope| format!("{}/{}", scope, path).replace("//", "/"));
|
||||
self.router.scope(path, |router| {
|
||||
let mut router = OpenapiRouter {
|
||||
router,
|
||||
scope: Some(new_scope.as_ref().map(String::as_ref).unwrap_or(path)),
|
||||
openapi_builder: &mut openapi_builder
|
||||
};
|
||||
callback(&mut router);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b, C, P> GetOpenapi for OpenapiRouter<'a, $implType<'b, C, P>>
|
||||
where
|
||||
C : PipelineHandleChain<P> + Copy + Send + Sync + 'static,
|
||||
|
@ -57,7 +80,7 @@ macro_rules! implOpenapiRouter {
|
|||
{
|
||||
let schema = (self.0).openapi_builder.add_schema::<Handler::Res>();
|
||||
|
||||
let path = format!("/{}", &self.1);
|
||||
let path = format!("{}/{}", self.0.scope.unwrap_or_default(), self.1);
|
||||
let mut item = (self.0).openapi_builder.remove_path(&path);
|
||||
item.get = Some(OperationDescription::new::<Handler>(schema).into_operation());
|
||||
(self.0).openapi_builder.add_path(path, item);
|
||||
|
@ -70,7 +93,7 @@ macro_rules! implOpenapiRouter {
|
|||
let schema = (self.0).openapi_builder.add_schema::<Handler::Res>();
|
||||
let id_schema = (self.0).openapi_builder.add_schema::<Handler::ID>();
|
||||
|
||||
let path = format!("/{}/{{id}}", &self.1);
|
||||
let path = format!("{}/{}/{{id}}", self.0.scope.unwrap_or_default(), self.1);
|
||||
let mut item = (self.0).openapi_builder.remove_path(&path);
|
||||
item.get = Some(OperationDescription::new::<Handler>(schema).add_path_param("id", id_schema).into_operation());
|
||||
(self.0).openapi_builder.add_path(path, item);
|
||||
|
@ -82,8 +105,8 @@ macro_rules! implOpenapiRouter {
|
|||
{
|
||||
let schema = (self.0).openapi_builder.add_schema::<Handler::Res>();
|
||||
|
||||
let path = format!("/{}/search", &self.1);
|
||||
let mut item = (self.0).openapi_builder.remove_path(&self.1);
|
||||
let path = format!("{}/{}/search", self.0.scope.unwrap_or_default(), self.1);
|
||||
let mut item = (self.0).openapi_builder.remove_path(&path);
|
||||
item.get = Some(OperationDescription::new::<Handler>(schema).with_query_params(Handler::Query::schema()).into_operation());
|
||||
(self.0).openapi_builder.add_path(path, item);
|
||||
|
||||
|
@ -98,7 +121,7 @@ macro_rules! implOpenapiRouter {
|
|||
let schema = (self.0).openapi_builder.add_schema::<Handler::Res>();
|
||||
let body_schema = (self.0).openapi_builder.add_schema::<Handler::Body>();
|
||||
|
||||
let path = format!("/{}", &self.1);
|
||||
let path = format!("{}/{}", self.0.scope.unwrap_or_default(), self.1);
|
||||
let mut item = (self.0).openapi_builder.remove_path(&path);
|
||||
item.post = Some(OperationDescription::new::<Handler>(schema).with_body::<Handler::Body>(body_schema).into_operation());
|
||||
(self.0).openapi_builder.add_path(path, item);
|
||||
|
@ -114,7 +137,7 @@ macro_rules! implOpenapiRouter {
|
|||
let schema = (self.0).openapi_builder.add_schema::<Handler::Res>();
|
||||
let body_schema = (self.0).openapi_builder.add_schema::<Handler::Body>();
|
||||
|
||||
let path = format!("/{}", &self.1);
|
||||
let path = format!("{}/{}", self.0.scope.unwrap_or_default(), self.1);
|
||||
let mut item = (self.0).openapi_builder.remove_path(&path);
|
||||
item.put = Some(OperationDescription::new::<Handler>(schema).with_body::<Handler::Body>(body_schema).into_operation());
|
||||
(self.0).openapi_builder.add_path(path, item);
|
||||
|
@ -131,7 +154,7 @@ macro_rules! implOpenapiRouter {
|
|||
let id_schema = (self.0).openapi_builder.add_schema::<Handler::ID>();
|
||||
let body_schema = (self.0).openapi_builder.add_schema::<Handler::Body>();
|
||||
|
||||
let path = format!("/{}/{{id}}", &self.1);
|
||||
let path = format!("{}/{}/{{id}}", self.0.scope.unwrap_or_default(), self.1);
|
||||
let mut item = (self.0).openapi_builder.remove_path(&path);
|
||||
item.put = Some(OperationDescription::new::<Handler>(schema).add_path_param("id", id_schema).with_body::<Handler::Body>(body_schema).into_operation());
|
||||
(self.0).openapi_builder.add_path(path, item);
|
||||
|
@ -143,7 +166,7 @@ macro_rules! implOpenapiRouter {
|
|||
{
|
||||
let schema = (self.0).openapi_builder.add_schema::<Handler::Res>();
|
||||
|
||||
let path = format!("/{}", &self.1);
|
||||
let path = format!("{}/{}", self.0.scope.unwrap_or_default(), self.1);
|
||||
let mut item = (self.0).openapi_builder.remove_path(&path);
|
||||
item.delete = Some(OperationDescription::new::<Handler>(schema).into_operation());
|
||||
(self.0).openapi_builder.add_path(path, item);
|
||||
|
@ -156,7 +179,7 @@ macro_rules! implOpenapiRouter {
|
|||
let schema = (self.0).openapi_builder.add_schema::<Handler::Res>();
|
||||
let id_schema = (self.0).openapi_builder.add_schema::<Handler::ID>();
|
||||
|
||||
let path = format!("/{}/{{id}}", &self.1);
|
||||
let path = format!("{}/{}/{{id}}", self.0.scope.unwrap_or_default(), self.1);
|
||||
let mut item = (self.0).openapi_builder.remove_path(&path);
|
||||
item.delete = Some(OperationDescription::new::<Handler>(schema).add_path_param("id", id_schema).into_operation());
|
||||
(self.0).openapi_builder.add_path(path, item);
|
||||
|
|
|
@ -324,6 +324,7 @@ macro_rules! implDrawResourceRoutes {
|
|||
{
|
||||
let router = OpenapiRouter {
|
||||
router: self,
|
||||
scope: None,
|
||||
openapi_builder: &mut OpenapiBuilder::new(info)
|
||||
};
|
||||
block(router);
|
||||
|
|
61
gotham_restful/tests/openapi_supports_scope.rs
Normal file
61
gotham_restful/tests/openapi_supports_scope.rs
Normal file
|
@ -0,0 +1,61 @@
|
|||
#[cfg(feature = "openapi")]
|
||||
mod openapi_supports_scope
|
||||
{
|
||||
|
||||
|
||||
use gotham::{
|
||||
router::builder::*,
|
||||
test::TestServer
|
||||
};
|
||||
use gotham_restful::*;
|
||||
use mime::TEXT_PLAIN;
|
||||
|
||||
const RESPONSE : &[u8] = b"This is the only valid response.";
|
||||
|
||||
#[derive(Resource)]
|
||||
#[resource(read_all)]
|
||||
struct FooResource;
|
||||
|
||||
#[read_all(FooResource)]
|
||||
fn read_all() -> Raw<&'static [u8]>
|
||||
{
|
||||
Raw::new(RESPONSE, TEXT_PLAIN)
|
||||
}
|
||||
|
||||
|
||||
fn test_response(server : &TestServer, path : &str)
|
||||
{
|
||||
let res = server.client().get(path).perform().unwrap().read_body().unwrap();
|
||||
let body : &[u8] = res.as_ref();
|
||||
assert_eq!(body, RESPONSE);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test()
|
||||
{
|
||||
let info = OpenapiInfo {
|
||||
title: "Test".to_owned(),
|
||||
version: "1.2.3".to_owned(),
|
||||
urls: Vec::new()
|
||||
};
|
||||
let server = TestServer::new(build_simple_router(|router| {
|
||||
router.with_openapi(info, |mut router| {
|
||||
router.resource::<FooResource>("foo1");
|
||||
router.scope("/bar", |router| {
|
||||
router.resource::<FooResource>("foo2");
|
||||
router.scope("/baz", |router| {
|
||||
router.resource::<FooResource>("foo3");
|
||||
})
|
||||
});
|
||||
router.resource::<FooResource>("foo4");
|
||||
});
|
||||
})).unwrap();
|
||||
|
||||
test_response(&server, "http://localhost/foo1");
|
||||
test_response(&server, "http://localhost/bar/foo2");
|
||||
test_response(&server, "http://localhost/bar/baz/foo3");
|
||||
test_response(&server, "http://localhost/foo4");
|
||||
}
|
||||
|
||||
|
||||
} // mod test
|
Loading…
Add table
Reference in a new issue