1
0
Fork 0
mirror of https://gitlab.com/msrd0/gotham-restful.git synced 2025-02-23 13:02:28 +00:00

add request bodies to openapi

This commit is contained in:
Dominic 2019-10-01 00:49:13 +02:00
parent 389740cd64
commit fe6a79008e
Signed by: msrd0
GPG key ID: DCC8C247452E98F9
6 changed files with 45 additions and 29 deletions

View file

@ -2,8 +2,7 @@
#[macro_use] extern crate serde; #[macro_use] extern crate serde;
pub use hyper::StatusCode; pub use hyper::StatusCode;
#[cfg(not(feature = "openapi"))] use serde::{de::DeserializeOwned, Serialize};
use serde::Serialize;
pub mod helper; pub mod helper;
@ -40,12 +39,12 @@ pub use routing::WithOpenapi;
/// that is serializable with serde, however, it is recommended to use the rest_struct! /// that is serializable with serde, however, it is recommended to use the rest_struct!
/// macro to create one. /// macro to create one.
#[cfg(not(feature = "openapi"))] #[cfg(not(feature = "openapi"))]
pub trait ResourceType : Serialize pub trait ResourceType : DeserializeOwned + Serialize
{ {
} }
#[cfg(not(feature = "openapi"))] #[cfg(not(feature = "openapi"))]
impl<T : Serialize> ResourceType for T impl<T : DeserializeOwned + Serialize> ResourceType for T
{ {
} }
@ -53,11 +52,11 @@ impl<T : Serialize> ResourceType for T
/// that is serializable with serde, however, it is recommended to use the rest_struct! /// that is serializable with serde, however, it is recommended to use the rest_struct!
/// macro to create one. /// macro to create one.
#[cfg(feature = "openapi")] #[cfg(feature = "openapi")]
pub trait ResourceType : OpenapiType pub trait ResourceType : OpenapiType + DeserializeOwned + Serialize
{ {
} }
#[cfg(feature = "openapi")] #[cfg(feature = "openapi")]
impl<T : OpenapiType> ResourceType for T impl<T : OpenapiType + DeserializeOwned + Serialize> ResourceType for T
{ {
} }

View file

@ -2,7 +2,8 @@ use crate::{
resource::*, resource::*,
result::*, result::*,
routing::*, routing::*,
OpenapiType OpenapiType,
ResourceType
}; };
use futures::future::ok; use futures::future::ok;
use gotham::{ use gotham::{
@ -68,7 +69,7 @@ impl OpenapiRouter
self.0.paths.insert(path.to_string(), Item(item)); self.0.paths.insert(path.to_string(), Item(item));
} }
fn add_schema<T : ResourceResult>(&mut self, path : &str, method : &str, desc : &str) -> String fn add_schema<T : OpenapiType>(&mut self, path : &str, method : &str, desc : &str) -> String
{ {
let name = T::schema_name().unwrap_or_else(|| format!("path_{}_{}_{}", path, method, desc)); let name = T::schema_name().unwrap_or_else(|| format!("path_{}_{}_{}", path, method, desc));
let item = Schema { let item = Schema {
@ -278,15 +279,16 @@ macro_rules! implOpenapiRouter {
fn create<Handler, Body, Res>(&mut self) fn create<Handler, Body, Res>(&mut self)
where where
Body : DeserializeOwned, Body : ResourceType,
Res : ResourceResult, Res : ResourceResult,
Handler : ResourceCreate<Body, Res> Handler : ResourceCreate<Body, Res>
{ {
let schema = (self.0).1.add_schema::<Res>(&self.1, "create", "result_body"); let schema = (self.0).1.add_schema::<Res>(&self.1, "create", "result_body");
let body_schema = (self.0).1.add_schema::<Body>(&self.1, "create", "body");
let path = format!("/{}", &self.1); let path = format!("/{}", &self.1);
let mut item = (self.0).1.remove_path(&path); let mut item = (self.0).1.remove_path(&path);
item.post = Some(new_operation(&schema, vec![], None)); item.post = Some(new_operation(&schema, vec![], Some(&body_schema)));
(self.0).1.add_path(path, item); (self.0).1.add_path(path, item);
(&mut *(self.0).0, self.1.to_string()).create::<Handler, Body, Res>() (&mut *(self.0).0, self.1.to_string()).create::<Handler, Body, Res>()
@ -294,15 +296,16 @@ macro_rules! implOpenapiRouter {
fn update_all<Handler, Body, Res>(&mut self) fn update_all<Handler, Body, Res>(&mut self)
where where
Body : DeserializeOwned, Body : ResourceType,
Res : ResourceResult, Res : ResourceResult,
Handler : ResourceUpdateAll<Body, Res> Handler : ResourceUpdateAll<Body, Res>
{ {
let schema = (self.0).1.add_schema::<Res>(&self.1, "update_all", "result_body"); let schema = (self.0).1.add_schema::<Res>(&self.1, "update_all", "result_body");
let body_schema = (self.0).1.add_schema::<Body>(&self.1, "create", "body");
let path = format!("/{}", &self.1); let path = format!("/{}", &self.1);
let mut item = (self.0).1.remove_path(&path); let mut item = (self.0).1.remove_path(&path);
item.put = Some(new_operation(&schema, vec![], None)); item.put = Some(new_operation(&schema, vec![], Some(&body_schema)));
(self.0).1.add_path(path, item); (self.0).1.add_path(path, item);
(&mut *(self.0).0, self.1.to_string()).update_all::<Handler, Body, Res>() (&mut *(self.0).0, self.1.to_string()).update_all::<Handler, Body, Res>()
@ -311,15 +314,16 @@ macro_rules! implOpenapiRouter {
fn update<Handler, ID, Body, Res>(&mut self) fn update<Handler, ID, Body, Res>(&mut self)
where where
ID : DeserializeOwned + Clone + RefUnwindSafe + Send + Sync + 'static, ID : DeserializeOwned + Clone + RefUnwindSafe + Send + Sync + 'static,
Body : DeserializeOwned, Body : ResourceType,
Res : ResourceResult, Res : ResourceResult,
Handler : ResourceUpdate<ID, Body, Res> Handler : ResourceUpdate<ID, Body, Res>
{ {
let schema = (self.0).1.add_schema::<Res>(&self.1, "update", "result_body"); let schema = (self.0).1.add_schema::<Res>(&self.1, "update", "result_body");
let body_schema = (self.0).1.add_schema::<Body>(&self.1, "create", "body");
let path = format!("/{}/{{id}}", &self.1); let path = format!("/{}/{{id}}", &self.1);
let mut item = (self.0).1.remove_path(&path); let mut item = (self.0).1.remove_path(&path);
item.put = Some(new_operation(&schema, vec!["id"], None)); item.put = Some(new_operation(&schema, vec!["id"], Some(&body_schema)));
(self.0).1.add_path(path, item); (self.0).1.add_path(path, item);
(&mut *(self.0).0, self.1.to_string()).update::<Handler, ID, Body, Res>() (&mut *(self.0).0, self.1.to_string()).update::<Handler, ID, Body, Res>()

View file

@ -1,11 +1,9 @@
use indexmap::IndexMap;
use openapiv3::{ use openapiv3::{
ArrayType, IntegerType, NumberType, ObjectType, ReferenceOr::Item, Schema, SchemaData, SchemaKind, StringType, Type ArrayType, IntegerType, NumberType, ObjectType, ReferenceOr::Item, Schema, SchemaData, SchemaKind, StringType, Type
}; };
use serde::Serialize;
pub trait OpenapiType : Serialize pub trait OpenapiType
{ {
fn schema_name() -> Option<String> fn schema_name() -> Option<String>
{ {

View file

@ -1,4 +1,4 @@
use crate::{DrawResourceRoutes, ResourceResult}; use crate::{DrawResourceRoutes, ResourceResult, ResourceType};
use gotham::state::State; use gotham::state::State;
use serde::de::DeserializeOwned; use serde::de::DeserializeOwned;
use std::panic::RefUnwindSafe; use std::panic::RefUnwindSafe;
@ -30,7 +30,7 @@ where
} }
/// Handle a POST request on the Resource root. /// Handle a POST request on the Resource root.
pub trait ResourceCreate<Body : DeserializeOwned, R : ResourceResult> pub trait ResourceCreate<Body : ResourceType, R : ResourceResult>
{ {
fn create(state : &mut State, body : Body) -> R; fn create(state : &mut State, body : Body) -> R;
} }
@ -42,7 +42,7 @@ pub trait ResourceUpdateAll<Body : DeserializeOwned, R : ResourceResult>
} }
/// Handle a PUT request on the Resource with an id. /// Handle a PUT request on the Resource with an id.
pub trait ResourceUpdate<ID, Body : DeserializeOwned, R : ResourceResult> pub trait ResourceUpdate<ID, Body : ResourceType, R : ResourceResult>
where where
ID : DeserializeOwned + Clone + RefUnwindSafe + Send + Sync + 'static ID : DeserializeOwned + Clone + RefUnwindSafe + Send + Sync + 'static
{ {

View file

@ -17,6 +17,20 @@ pub trait ResourceResult
fn to_schema() -> SchemaKind; fn to_schema() -> SchemaKind;
} }
#[cfg(feature = "openapi")]
impl<Res : ResourceResult> crate::OpenapiType for Res
{
fn schema_name() -> Option<String>
{
Self::schema_name()
}
fn to_schema() -> SchemaKind
{
Self::to_schema()
}
}
/// The default json returned on an 500 Internal Server Error. /// The default json returned on an 500 Internal Server Error.
#[derive(Debug, Serialize)] #[derive(Debug, Serialize)]
pub struct ResourceError pub struct ResourceError

View file

@ -1,6 +1,7 @@
use crate::{ use crate::{
resource::*, resource::*,
result::{ResourceError, ResourceResult}, result::{ResourceError, ResourceResult},
ResourceType,
StatusCode StatusCode
}; };
#[cfg(feature = "openapi")] #[cfg(feature = "openapi")]
@ -66,20 +67,20 @@ pub trait DrawResourceRoutes
fn create<Handler, Body, Res>(&mut self) fn create<Handler, Body, Res>(&mut self)
where where
Body : DeserializeOwned, Body : ResourceType,
Res : ResourceResult, Res : ResourceResult,
Handler : ResourceCreate<Body, Res>; Handler : ResourceCreate<Body, Res>;
fn update_all<Handler, Body, Res>(&mut self) fn update_all<Handler, Body, Res>(&mut self)
where where
Body : DeserializeOwned, Body : ResourceType,
Res : ResourceResult, Res : ResourceResult,
Handler : ResourceUpdateAll<Body, Res>; Handler : ResourceUpdateAll<Body, Res>;
fn update<Handler, ID, Body, Res>(&mut self) fn update<Handler, ID, Body, Res>(&mut self)
where where
ID : DeserializeOwned + Clone + RefUnwindSafe + Send + Sync + 'static, ID : DeserializeOwned + Clone + RefUnwindSafe + Send + Sync + 'static,
Body : DeserializeOwned, Body : ResourceType,
Res : ResourceResult, Res : ResourceResult,
Handler : ResourceUpdate<ID, Body, Res>; Handler : ResourceUpdate<ID, Body, Res>;
@ -176,7 +177,7 @@ where
fn create_handler<Handler, Body, Res>(state : State) -> Box<HandlerFuture> fn create_handler<Handler, Body, Res>(state : State) -> Box<HandlerFuture>
where where
Body : DeserializeOwned, Body : ResourceType,
Res : ResourceResult, Res : ResourceResult,
Handler : ResourceCreate<Body, Res> Handler : ResourceCreate<Body, Res>
{ {
@ -185,7 +186,7 @@ where
fn update_all_handler<Handler, Body, Res>(state : State) -> Box<HandlerFuture> fn update_all_handler<Handler, Body, Res>(state : State) -> Box<HandlerFuture>
where where
Body : DeserializeOwned, Body : ResourceType,
Res : ResourceResult, Res : ResourceResult,
Handler : ResourceUpdateAll<Body, Res> Handler : ResourceUpdateAll<Body, Res>
{ {
@ -195,7 +196,7 @@ where
fn update_handler<Handler, ID, Body, Res>(state : State) -> Box<HandlerFuture> fn update_handler<Handler, ID, Body, Res>(state : State) -> Box<HandlerFuture>
where where
ID : DeserializeOwned + Clone + RefUnwindSafe + Send + Sync + 'static, ID : DeserializeOwned + Clone + RefUnwindSafe + Send + Sync + 'static,
Body : DeserializeOwned, Body : ResourceType,
Res : ResourceResult, Res : ResourceResult,
Handler : ResourceUpdate<ID, Body, Res> Handler : ResourceUpdate<ID, Body, Res>
{ {
@ -286,7 +287,7 @@ macro_rules! implDrawResourceRoutes {
fn create<Handler, Body, Res>(&mut self) fn create<Handler, Body, Res>(&mut self)
where where
Body : DeserializeOwned, Body : ResourceType,
Res : ResourceResult, Res : ResourceResult,
Handler : ResourceCreate<Body, Res> Handler : ResourceCreate<Body, Res>
{ {
@ -296,7 +297,7 @@ macro_rules! implDrawResourceRoutes {
fn update_all<Handler, Body, Res>(&mut self) fn update_all<Handler, Body, Res>(&mut self)
where where
Body : DeserializeOwned, Body : ResourceType,
Res : ResourceResult, Res : ResourceResult,
Handler : ResourceUpdateAll<Body, Res> Handler : ResourceUpdateAll<Body, Res>
{ {
@ -307,7 +308,7 @@ macro_rules! implDrawResourceRoutes {
fn update<Handler, ID, Body, Res>(&mut self) fn update<Handler, ID, Body, Res>(&mut self)
where where
ID : DeserializeOwned + Clone + RefUnwindSafe + Send + Sync + 'static, ID : DeserializeOwned + Clone + RefUnwindSafe + Send + Sync + 'static,
Body : DeserializeOwned, Body : ResourceType,
Res : ResourceResult, Res : ResourceResult,
Handler : ResourceUpdate<ID, Body, Res> Handler : ResourceUpdate<ID, Body, Res>
{ {