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

first valid openapi spec generated

This commit is contained in:
Dominic 2019-09-30 23:53:55 +02:00
parent 681482ece3
commit d9b4b22af3
Signed by: msrd0
GPG key ID: DCC8C247452E98F9
4 changed files with 130 additions and 20 deletions

View file

@ -1,4 +1,11 @@
#[cfg(feature = "openapi")]
pub mod openapi
{
pub use indexmap::IndexMap;
pub use openapiv3::{ObjectType, ReferenceOr, Schema, SchemaData, SchemaKind, Type};
}
#[cfg(not(feature = "openapi"))]
#[macro_export]
macro_rules! rest_struct {
($struct_name:ident { $($field_id:ident : $field_ty:ty),* }) => {
@ -10,6 +17,52 @@ macro_rules! rest_struct {
}
}
#[cfg(feature = "openapi")]
#[macro_export]
macro_rules! rest_struct {
($struct_name:ident { $($field_id:ident : $field_ty:ty),* }) => {
#[derive(serde::Deserialize, serde::Serialize)]
struct $struct_name
{
$($field_id : $field_ty),*
}
impl ::gotham_restful::OpenapiType for $struct_name
{
fn schema_name() -> Option<String>
{
Some(stringify!($struct_name).to_string())
}
fn to_schema() -> ::gotham_restful::helper::openapi::SchemaKind
{
use ::gotham_restful::helper::openapi::*;
let mut properties : IndexMap<String, ReferenceOr<Box<Schema>>> = IndexMap::new();
let mut required : Vec<String> = Vec::new();
$(
properties.insert(
stringify!($field_id).to_string(),
ReferenceOr::Item(Box::new(Schema {
schema_data: SchemaData::default(),
schema_kind: <$field_ty>::to_schema()
}))
);
)*
SchemaKind::Type(Type::Object(ObjectType {
properties,
required,
additional_properties: None,
min_properties: None,
max_properties: None
}))
}
}
}
}
#[macro_export]
macro_rules! rest_resource {
($res_name:ident, $route:ident => $setup:block) => {

View file

@ -15,7 +15,8 @@ use indexmap::IndexMap;
use log::error;
use mime::{APPLICATION_JSON, TEXT_PLAIN};
use openapiv3::{
MediaType, OpenAPI, Operation, PathItem, Paths, ReferenceOr, ReferenceOr::Item, Response, Responses, Server, StatusCode
Components, MediaType, OpenAPI, Operation, PathItem, Paths, ReferenceOr, ReferenceOr::Item, ReferenceOr::Reference,
Response, Responses, Schema, SchemaData, Server, StatusCode
};
use serde::de::DeserializeOwned;
use std::panic::RefUnwindSafe;
@ -57,24 +58,27 @@ impl OpenapiRouter
{
return item;
}
return PathItem {
get: None,
put: None,
post: None,
delete: None,
options: None,
head: None,
patch: None,
trace: None,
servers: Vec::new(),
parameters: Vec::new()
};
return PathItem::default()
}
fn add_path<Path : ToString>(&mut self, path : Path, item : PathItem)
{
self.0.paths.insert(path.to_string(), Item(item));
}
fn add_schema<Name : ToString>(&mut self, name : Name, item : Schema)
{
match &mut self.0.components {
Some(comp) => {
comp.schemas.insert(name.to_string(), Item(item));
},
None => {
let mut comp = Components::default();
comp.schemas.insert(name.to_string(), Item(item));
self.0.components = Some(comp);
}
};
}
}
#[derive(Clone)]
@ -159,11 +163,21 @@ macro_rules! implOpenapiRouter {
Res : ResourceResult,
Handler : ResourceReadAll<Res>
{
let path = &self.1;
let mut item = (self.0).1.remove_path(path);
let schema = Res::schema_name().unwrap_or_else(|| {
format!("Resource_{}_ReadAllResult", self.1)
});
(self.0).1.add_schema(&schema, Schema {
schema_data: SchemaData::default(),
schema_kind: Res::to_schema()
});
let path = format!("/{}", &self.1);
let mut item = (self.0).1.remove_path(&path);
let mut content : IndexMap<String, MediaType> = IndexMap::new();
content.insert(APPLICATION_JSON.to_string(), MediaType {
schema: None, // TODO
schema: Some(Reference {
reference: format!("#/components/schemas/{}", schema)
}),
example: None,
examples: IndexMap::new(),
encoding: IndexMap::new()

View file

@ -1,12 +1,17 @@
use indexmap::IndexMap;
use openapiv3::{
IntegerType, NumberType, ObjectType, SchemaKind, StringType, Type
ArrayType, IntegerType, NumberType, ObjectType, ReferenceOr::Item, Schema, SchemaData, SchemaKind, StringType, Type
};
use serde::Serialize;
pub trait OpenapiType : Serialize
{
fn schema_name() -> Option<String>
{
None
}
fn to_schema() -> SchemaKind;
}
@ -67,3 +72,24 @@ macro_rules! str_types {
}
str_types!(String, &str);
impl<T : OpenapiType> OpenapiType for Vec<T>
{
fn schema_name() -> Option<String>
{
T::schema_name().map(|name| format!("{}Array", name))
}
fn to_schema() -> SchemaKind
{
SchemaKind::Type(Type::Array(ArrayType {
items: Item(Box::new(Schema {
schema_data: SchemaData::default(),
schema_kind: T::to_schema()
})),
min_items: None,
max_items: None,
unique_items: false
}))
}
}

View file

@ -8,7 +8,10 @@ use std::error::Error;
pub trait ResourceResult
{
fn to_json(&self) -> Result<(StatusCode, String), SerdeJsonError>;
#[cfg(feature = "openapi")]
fn schema_name() -> Option<String>;
#[cfg(feature = "openapi")]
fn to_schema() -> SchemaKind;
}
@ -44,7 +47,14 @@ impl<R : ResourceType, E : Error> ResourceResult for Result<R, E>
}
})
}
#[cfg(feature = "openapi")]
fn schema_name() -> Option<String>
{
R::schema_name()
}
#[cfg(feature = "openapi")]
fn to_schema() -> SchemaKind
{
R::to_schema()
@ -68,7 +78,14 @@ impl<T : ResourceType> ResourceResult for Success<T>
{
Ok((StatusCode::OK, serde_json::to_string(&self.0)?))
}
#[cfg(feature = "openapi")]
fn schema_name() -> Option<String>
{
T::schema_name()
}
#[cfg(feature = "openapi")]
fn to_schema() -> SchemaKind
{
T::to_schema()