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

Proper OpenAPI type for path parameters (Fixes #18)

This commit is contained in:
Dominic 2020-04-29 19:10:11 +02:00
parent 9fd0bceaf4
commit 45eac21726
Signed by: msrd0
GPG key ID: DCC8C247452E98F9
4 changed files with 28 additions and 16 deletions

View file

@ -2,7 +2,6 @@ use crate::{
resource::*, resource::*,
result::*, result::*,
OpenapiSchema, OpenapiSchema,
OpenapiType,
RequestBody RequestBody
}; };
use super::SECURITY_NAME; use super::SECURITY_NAME;
@ -18,7 +17,7 @@ use openapiv3::{
#[derive(Default)] #[derive(Default)]
struct OperationParams<'a> struct OperationParams<'a>
{ {
path_params : Vec<&'a str>, path_params : Vec<(&'a str, ReferenceOr<Schema>)>,
query_params : Option<OpenapiSchema> query_params : Option<OpenapiSchema>
} }
@ -30,11 +29,11 @@ impl<'a> OperationParams<'a>
{ {
params.push(Item(Parameter::Path { params.push(Item(Parameter::Path {
parameter_data: ParameterData { parameter_data: ParameterData {
name: (*param).to_string(), name: (*param).0.to_string(),
description: None, description: None,
required: true, required: true,
deprecated: None, deprecated: None,
format: ParameterSchemaOrContent::Schema(Item(String::schema().into_schema())), format: ParameterSchemaOrContent::Schema((*param).1.clone()),
example: None, example: None,
examples: IndexMap::new() examples: IndexMap::new()
}, },
@ -110,9 +109,9 @@ impl<'a> OperationDescription<'a>
} }
} }
pub fn with_path_params(mut self, params : Vec<&'a str>) -> Self pub fn add_path_param(mut self, name : &'a str, schema : ReferenceOr<Schema>) -> Self
{ {
self.params.path_params = params; self.params.path_params.push((name, schema));
self self
} }
@ -192,7 +191,7 @@ impl<'a> OperationDescription<'a>
#[cfg(test)] #[cfg(test)]
mod test mod test
{ {
use crate::ResourceResult; use crate::{OpenapiType, ResourceResult};
use super::*; use super::*;
#[test] #[test]

View file

@ -61,10 +61,11 @@ macro_rules! implOpenapiRouter {
fn read<Handler : ResourceRead>(&mut self) fn read<Handler : ResourceRead>(&mut self)
{ {
let schema = (self.0).1.add_schema::<Handler::Res>(); let schema = (self.0).1.add_schema::<Handler::Res>();
let id_schema = (self.0).1.add_schema::<Handler::ID>();
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.get = Some(OperationDescription::new::<Handler>(schema).with_path_params(vec!["id"]).into_operation()); item.get = Some(OperationDescription::new::<Handler>(schema).add_path_param("id", id_schema).into_operation());
(self.0).1.add_path(path, item); (self.0).1.add_path(path, item);
(&mut *(self.0).0, self.1).read::<Handler>() (&mut *(self.0).0, self.1).read::<Handler>()
@ -120,11 +121,12 @@ macro_rules! implOpenapiRouter {
Handler::Body : 'static Handler::Body : 'static
{ {
let schema = (self.0).1.add_schema::<Handler::Res>(); let schema = (self.0).1.add_schema::<Handler::Res>();
let id_schema = (self.0).1.add_schema::<Handler::ID>();
let body_schema = (self.0).1.add_schema::<Handler::Body>(); let body_schema = (self.0).1.add_schema::<Handler::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(OperationDescription::new::<Handler>(schema).with_path_params(vec!["id"]).with_body::<Handler::Body>(body_schema).into_operation()); item.put = Some(OperationDescription::new::<Handler>(schema).add_path_param("id", id_schema).with_body::<Handler::Body>(body_schema).into_operation());
(self.0).1.add_path(path, item); (self.0).1.add_path(path, item);
(&mut *(self.0).0, self.1).update::<Handler>() (&mut *(self.0).0, self.1).update::<Handler>()
@ -145,10 +147,11 @@ macro_rules! implOpenapiRouter {
fn delete<Handler : ResourceDelete>(&mut self) fn delete<Handler : ResourceDelete>(&mut self)
{ {
let schema = (self.0).1.add_schema::<Handler::Res>(); let schema = (self.0).1.add_schema::<Handler::Res>();
let id_schema = (self.0).1.add_schema::<Handler::ID>();
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.delete = Some(OperationDescription::new::<Handler>(schema).with_path_params(vec!["id"]).into_operation()); item.delete = Some(OperationDescription::new::<Handler>(schema).add_path_param("id", id_schema).into_operation());
(self.0).1.add_path(path, item); (self.0).1.add_path(path, item);
(&mut *(self.0).0, self.1).delete::<Handler>() (&mut *(self.0).0, self.1).delete::<Handler>()

View file

@ -1,13 +1,11 @@
use crate::{DrawResourceRoutes, RequestBody, ResourceResult, ResourceType}; use crate::{DrawResourceRoutes, RequestBody, ResourceID, ResourceResult, ResourceType};
use gotham::{ use gotham::{
extractor::QueryStringExtractor, extractor::QueryStringExtractor,
hyper::Body, hyper::Body,
state::State state::State
}; };
use serde::de::DeserializeOwned;
use std::{ use std::{
future::Future, future::Future,
panic::RefUnwindSafe,
pin::Pin pin::Pin
}; };
@ -48,7 +46,7 @@ pub trait ResourceReadAll : ResourceMethod
/// Handle a GET request on the Resource with an id. /// Handle a GET request on the Resource with an id.
pub trait ResourceRead : ResourceMethod pub trait ResourceRead : ResourceMethod
{ {
type ID : DeserializeOwned + Clone + RefUnwindSafe + Send + Sync + 'static; type ID : ResourceID + 'static;
fn read(state : State, id : Self::ID) -> Pin<Box<dyn Future<Output = (State, Self::Res)> + Send>>; fn read(state : State, id : Self::ID) -> Pin<Box<dyn Future<Output = (State, Self::Res)> + Send>>;
} }
@ -81,7 +79,7 @@ pub trait ResourceUpdateAll : ResourceMethod
pub trait ResourceUpdate : ResourceMethod pub trait ResourceUpdate : ResourceMethod
{ {
type Body : RequestBody; type Body : RequestBody;
type ID : DeserializeOwned + Clone + RefUnwindSafe + Send + Sync + 'static; type ID : ResourceID + 'static;
fn update(state : State, id : Self::ID, body : Self::Body) -> Pin<Box<dyn Future<Output = (State, Self::Res)> + Send>>; fn update(state : State, id : Self::ID, body : Self::Body) -> Pin<Box<dyn Future<Output = (State, Self::Res)> + Send>>;
} }
@ -95,7 +93,7 @@ pub trait ResourceDeleteAll : ResourceMethod
/// Handle a DELETE request on the Resource with an id. /// Handle a DELETE request on the Resource with an id.
pub trait ResourceDelete : ResourceMethod pub trait ResourceDelete : ResourceMethod
{ {
type ID : DeserializeOwned + Clone + RefUnwindSafe + Send + Sync + 'static; type ID : ResourceID + 'static;
fn delete(state : State, id : Self::ID) -> Pin<Box<dyn Future<Output = (State, Self::Res)> + Send>>; fn delete(state : State, id : Self::ID) -> Pin<Box<dyn Future<Output = (State, Self::Res)> + Send>>;
} }

View file

@ -5,6 +5,7 @@ use crate::result::ResourceError;
use gotham::hyper::body::Bytes; use gotham::hyper::body::Bytes;
use mime::{Mime, APPLICATION_JSON}; use mime::{Mime, APPLICATION_JSON};
use serde::{de::DeserializeOwned, Serialize}; use serde::{de::DeserializeOwned, Serialize};
use std::panic::RefUnwindSafe;
#[cfg(not(feature = "openapi"))] #[cfg(not(feature = "openapi"))]
pub trait ResourceType pub trait ResourceType
@ -78,3 +79,14 @@ impl<T : ResourceType + DeserializeOwned> RequestBody for T
Some(vec![APPLICATION_JSON]) Some(vec![APPLICATION_JSON])
} }
} }
/// A type than can be used as a parameter to a resource method. Implemented for every type
/// that is deserialize and thread-safe. If the `openapi` feature is used, it must also be of
/// type `OpenapiType`.
pub trait ResourceID : ResourceType + DeserializeOwned + Clone + RefUnwindSafe + Send + Sync
{
}
impl<T : ResourceType + DeserializeOwned + Clone + RefUnwindSafe + Send + Sync> ResourceID for T
{
}