mirror of
https://gitlab.com/msrd0/gotham-restful.git
synced 2025-02-23 04:52:28 +00:00
introduce OpenapiSchema type
This commit is contained in:
parent
0619e69925
commit
d1c7ac5887
5 changed files with 85 additions and 115 deletions
|
@ -29,14 +29,9 @@ macro_rules! rest_struct {
|
|||
|
||||
impl ::gotham_restful::OpenapiType for $struct_name
|
||||
{
|
||||
fn schema_name() -> Option<String>
|
||||
fn to_schema() -> ::gotham_restful::OpenapiSchema
|
||||
{
|
||||
Some(stringify!($struct_name).to_string())
|
||||
}
|
||||
|
||||
fn to_schema() -> ::gotham_restful::helper::openapi::SchemaKind
|
||||
{
|
||||
use ::gotham_restful::helper::openapi::*;
|
||||
use ::gotham_restful::{helper::openapi::*, OpenapiSchema};
|
||||
|
||||
let mut properties : IndexMap<String, ReferenceOr<Box<Schema>>> = IndexMap::new();
|
||||
let mut required : Vec<String> = Vec::new();
|
||||
|
@ -44,31 +39,23 @@ macro_rules! rest_struct {
|
|||
$(
|
||||
properties.insert(
|
||||
stringify!($field_id).to_string(),
|
||||
ReferenceOr::Item(Box::new(Schema {
|
||||
schema_data: SchemaData {
|
||||
nullable: false,
|
||||
read_only: false,
|
||||
write_only: false,
|
||||
deprecated: false,
|
||||
external_docs: None,
|
||||
example: None,
|
||||
title: <$field_ty>::schema_name(),
|
||||
description: None,
|
||||
discriminator: None,
|
||||
default: None
|
||||
},
|
||||
schema_kind: <$field_ty>::to_schema()
|
||||
}))
|
||||
ReferenceOr::Item(Box::new(<$field_ty>::to_schema().to_schema()))
|
||||
);
|
||||
)*
|
||||
|
||||
SchemaKind::Type(Type::Object(ObjectType {
|
||||
let schema = SchemaKind::Type(Type::Object(ObjectType {
|
||||
properties,
|
||||
required,
|
||||
additional_properties: None,
|
||||
min_properties: None,
|
||||
max_properties: None
|
||||
}))
|
||||
}));
|
||||
|
||||
OpenapiSchema {
|
||||
name: Some(stringify!($struct_name).to_string()),
|
||||
nullable: false,
|
||||
schema
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ pub mod openapi;
|
|||
#[cfg(feature = "openapi")]
|
||||
pub use openapi::{
|
||||
router::{GetOpenapi, OpenapiRouter},
|
||||
types::OpenapiType
|
||||
types::{OpenapiSchema, OpenapiType}
|
||||
};
|
||||
|
||||
mod resource;
|
||||
|
|
|
@ -19,7 +19,7 @@ use mime::{APPLICATION_JSON, TEXT_PLAIN};
|
|||
use openapiv3::{
|
||||
Components, MediaType, OpenAPI, Operation, Parameter, ParameterData, ParameterSchemaOrContent, PathItem,
|
||||
PathStyle, Paths, ReferenceOr, ReferenceOr::Item, ReferenceOr::Reference, RequestBody, Response, Responses,
|
||||
Schema, SchemaData, Server, StatusCode
|
||||
Server, StatusCode
|
||||
};
|
||||
use serde::de::DeserializeOwned;
|
||||
use std::panic::RefUnwindSafe;
|
||||
|
@ -71,22 +71,9 @@ impl OpenapiRouter
|
|||
|
||||
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 item = Schema {
|
||||
schema_data: SchemaData {
|
||||
nullable: false,
|
||||
read_only: false,
|
||||
write_only: false,
|
||||
deprecated: false,
|
||||
external_docs: None,
|
||||
example: None,
|
||||
title: Some(name.to_string()),
|
||||
description: None,
|
||||
discriminator: None,
|
||||
default: None
|
||||
},
|
||||
schema_kind: T::to_schema()
|
||||
};
|
||||
let schema = T::to_schema();
|
||||
let name = schema.name.clone().unwrap_or_else(|| format!("path_{}_{}_{}", path, method, desc));
|
||||
let item = schema.to_schema();
|
||||
match &mut self.0.components {
|
||||
Some(comp) => {
|
||||
comp.schemas.insert(name.to_string(), Item(item));
|
||||
|
@ -181,10 +168,7 @@ fn new_operation(schema : &str, path_params : Vec<&str>, body_schema : Option<&s
|
|||
description: None,
|
||||
required: true,
|
||||
deprecated: None,
|
||||
format: ParameterSchemaOrContent::Schema(Item(Schema {
|
||||
schema_data: SchemaData::default(),
|
||||
schema_kind: String::to_schema()
|
||||
})),
|
||||
format: ParameterSchemaOrContent::Schema(Item(String::to_schema().to_schema())),
|
||||
example: None,
|
||||
examples: IndexMap::new()
|
||||
},
|
||||
|
|
|
@ -3,34 +3,68 @@ use chrono::{
|
|||
Date, DateTime, FixedOffset, Local, NaiveDate, NaiveDateTime, Utc
|
||||
};
|
||||
use openapiv3::{
|
||||
ArrayType, IntegerType, NumberType, ObjectType, ReferenceOr::Item, Schema, SchemaData, SchemaKind,
|
||||
StringFormat, StringType, Type, VariantOrUnknownOrEmpty
|
||||
ArrayType, IntegerType, NumberType, ObjectType, ReferenceOr::Item, ReferenceOr::Reference, Schema,
|
||||
SchemaData, SchemaKind, StringFormat, StringType, Type, VariantOrUnknownOrEmpty
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct OpenapiSchema
|
||||
{
|
||||
/// The name of this schema. If it is None, the schema will be inlined.
|
||||
pub name : Option<String>,
|
||||
pub nullable : bool,
|
||||
pub schema : SchemaKind
|
||||
}
|
||||
|
||||
impl OpenapiSchema
|
||||
{
|
||||
pub fn new(schema : SchemaKind) -> Self
|
||||
{
|
||||
Self {
|
||||
name: None,
|
||||
nullable: false,
|
||||
schema
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_schema(self) -> Schema
|
||||
{
|
||||
Schema {
|
||||
schema_data: SchemaData {
|
||||
nullable: self.nullable,
|
||||
read_only: false,
|
||||
write_only: false,
|
||||
deprecated: false,
|
||||
external_docs: None,
|
||||
example: None,
|
||||
title: self.name,
|
||||
description: None,
|
||||
discriminator: None,
|
||||
default: None
|
||||
},
|
||||
schema_kind: self.schema
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait OpenapiType
|
||||
{
|
||||
fn schema_name() -> Option<String>
|
||||
{
|
||||
None
|
||||
}
|
||||
|
||||
fn to_schema() -> SchemaKind;
|
||||
fn to_schema() -> OpenapiSchema;
|
||||
}
|
||||
|
||||
impl OpenapiType for ()
|
||||
{
|
||||
fn to_schema() -> SchemaKind
|
||||
fn to_schema() -> OpenapiSchema
|
||||
{
|
||||
SchemaKind::Type(Type::Object(ObjectType::default()))
|
||||
OpenapiSchema::new(SchemaKind::Type(Type::Object(ObjectType::default())))
|
||||
}
|
||||
}
|
||||
|
||||
impl OpenapiType for bool
|
||||
{
|
||||
fn to_schema() -> SchemaKind
|
||||
fn to_schema() -> OpenapiSchema
|
||||
{
|
||||
SchemaKind::Type(Type::Boolean{})
|
||||
OpenapiSchema::new(SchemaKind::Type(Type::Boolean{}))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -38,9 +72,9 @@ macro_rules! int_types {
|
|||
($($int_ty:ty),*) => {$(
|
||||
impl OpenapiType for $int_ty
|
||||
{
|
||||
fn to_schema() -> SchemaKind
|
||||
fn to_schema() -> OpenapiSchema
|
||||
{
|
||||
SchemaKind::Type(Type::Integer(IntegerType::default()))
|
||||
OpenapiSchema::new(SchemaKind::Type(Type::Integer(IntegerType::default())))
|
||||
}
|
||||
}
|
||||
)*}
|
||||
|
@ -52,9 +86,9 @@ macro_rules! num_types {
|
|||
($($num_ty:ty),*) => {$(
|
||||
impl OpenapiType for $num_ty
|
||||
{
|
||||
fn to_schema() -> SchemaKind
|
||||
fn to_schema() -> OpenapiSchema
|
||||
{
|
||||
SchemaKind::Type(Type::Number(NumberType::default()))
|
||||
OpenapiSchema::new(SchemaKind::Type(Type::Number(NumberType::default())))
|
||||
}
|
||||
}
|
||||
)*}
|
||||
|
@ -66,9 +100,9 @@ macro_rules! str_types {
|
|||
($($str_ty:ty),*) => {$(
|
||||
impl OpenapiType for $str_ty
|
||||
{
|
||||
fn to_schema() -> SchemaKind
|
||||
fn to_schema() -> OpenapiSchema
|
||||
{
|
||||
SchemaKind::Type(Type::String(StringType::default()))
|
||||
OpenapiSchema::new(SchemaKind::Type(Type::String(StringType::default())))
|
||||
}
|
||||
}
|
||||
)*};
|
||||
|
@ -76,13 +110,13 @@ macro_rules! str_types {
|
|||
(format = $format:ident, $($str_ty:ty),*) => {$(
|
||||
impl OpenapiType for $str_ty
|
||||
{
|
||||
fn to_schema() -> SchemaKind
|
||||
fn to_schema() -> OpenapiSchema
|
||||
{
|
||||
SchemaKind::Type(Type::String(StringType {
|
||||
OpenapiSchema::new(SchemaKind::Type(Type::String(StringType {
|
||||
format: VariantOrUnknownOrEmpty::Item(StringFormat::$format),
|
||||
pattern: None,
|
||||
enumeration: Vec::new()
|
||||
}))
|
||||
})))
|
||||
}
|
||||
}
|
||||
)*};
|
||||
|
@ -92,33 +126,18 @@ str_types!(String, &str);
|
|||
|
||||
impl<T : OpenapiType> OpenapiType for Vec<T>
|
||||
{
|
||||
fn schema_name() -> Option<String>
|
||||
fn to_schema() -> OpenapiSchema
|
||||
{
|
||||
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 {
|
||||
nullable: false,
|
||||
read_only: false,
|
||||
write_only: false,
|
||||
deprecated: false,
|
||||
external_docs: None,
|
||||
example: None,
|
||||
title: T::schema_name(),
|
||||
description: None,
|
||||
discriminator: None,
|
||||
default: None
|
||||
},
|
||||
schema_kind: T::to_schema()
|
||||
})),
|
||||
let schema = T::to_schema();
|
||||
OpenapiSchema::new(SchemaKind::Type(Type::Array(ArrayType {
|
||||
items: match schema.name {
|
||||
Some(name) => Reference { reference: format!("#/components/schemas/{}", name) },
|
||||
None => Item(Box::new(schema.to_schema()))
|
||||
},
|
||||
min_items: None,
|
||||
max_items: None,
|
||||
unique_items: false
|
||||
}))
|
||||
})))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::{ResourceType, StatusCode};
|
||||
#[cfg(feature = "openapi")]
|
||||
use openapiv3::SchemaKind;
|
||||
use crate::OpenapiSchema;
|
||||
use serde::Serialize;
|
||||
use serde_json::error::Error as SerdeJsonError;
|
||||
use std::error::Error;
|
||||
|
@ -11,21 +11,13 @@ 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;
|
||||
fn to_schema() -> OpenapiSchema;
|
||||
}
|
||||
|
||||
#[cfg(feature = "openapi")]
|
||||
impl<Res : ResourceResult> crate::OpenapiType for Res
|
||||
{
|
||||
fn schema_name() -> Option<String>
|
||||
{
|
||||
Self::schema_name()
|
||||
}
|
||||
|
||||
fn to_schema() -> SchemaKind
|
||||
fn to_schema() -> OpenapiSchema
|
||||
{
|
||||
Self::to_schema()
|
||||
}
|
||||
|
@ -64,13 +56,7 @@ 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
|
||||
fn to_schema() -> OpenapiSchema
|
||||
{
|
||||
R::to_schema()
|
||||
}
|
||||
|
@ -95,13 +81,7 @@ impl<T : ResourceType> ResourceResult for Success<T>
|
|||
}
|
||||
|
||||
#[cfg(feature = "openapi")]
|
||||
fn schema_name() -> Option<String>
|
||||
{
|
||||
T::schema_name()
|
||||
}
|
||||
|
||||
#[cfg(feature = "openapi")]
|
||||
fn to_schema() -> SchemaKind
|
||||
fn to_schema() -> OpenapiSchema
|
||||
{
|
||||
T::to_schema()
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue