From 45eac2172648bf5d33c11e4444f18ee72730ac2d Mon Sep 17 00:00:00 2001 From: Dominic Date: Wed, 29 Apr 2020 19:10:11 +0200 Subject: [PATCH] Proper OpenAPI type for path parameters (Fixes #18) --- gotham_restful/src/openapi/operation.rs | 13 ++++++------- gotham_restful/src/openapi/router.rs | 9 ++++++--- gotham_restful/src/resource.rs | 10 ++++------ gotham_restful/src/types.rs | 12 ++++++++++++ 4 files changed, 28 insertions(+), 16 deletions(-) diff --git a/gotham_restful/src/openapi/operation.rs b/gotham_restful/src/openapi/operation.rs index 77d0698..e949301 100644 --- a/gotham_restful/src/openapi/operation.rs +++ b/gotham_restful/src/openapi/operation.rs @@ -2,7 +2,6 @@ use crate::{ resource::*, result::*, OpenapiSchema, - OpenapiType, RequestBody }; use super::SECURITY_NAME; @@ -18,7 +17,7 @@ use openapiv3::{ #[derive(Default)] struct OperationParams<'a> { - path_params : Vec<&'a str>, + path_params : Vec<(&'a str, ReferenceOr)>, query_params : Option } @@ -30,11 +29,11 @@ impl<'a> OperationParams<'a> { params.push(Item(Parameter::Path { parameter_data: ParameterData { - name: (*param).to_string(), + name: (*param).0.to_string(), description: None, required: true, deprecated: None, - format: ParameterSchemaOrContent::Schema(Item(String::schema().into_schema())), + format: ParameterSchemaOrContent::Schema((*param).1.clone()), example: None, 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) -> Self { - self.params.path_params = params; + self.params.path_params.push((name, schema)); self } @@ -192,7 +191,7 @@ impl<'a> OperationDescription<'a> #[cfg(test)] mod test { - use crate::ResourceResult; + use crate::{OpenapiType, ResourceResult}; use super::*; #[test] diff --git a/gotham_restful/src/openapi/router.rs b/gotham_restful/src/openapi/router.rs index 36783d3..24ead43 100644 --- a/gotham_restful/src/openapi/router.rs +++ b/gotham_restful/src/openapi/router.rs @@ -61,10 +61,11 @@ macro_rules! implOpenapiRouter { fn read(&mut self) { let schema = (self.0).1.add_schema::(); + let id_schema = (self.0).1.add_schema::(); let path = format!("/{}/{{id}}", &self.1); let mut item = (self.0).1.remove_path(&path); - item.get = Some(OperationDescription::new::(schema).with_path_params(vec!["id"]).into_operation()); + item.get = Some(OperationDescription::new::(schema).add_path_param("id", id_schema).into_operation()); (self.0).1.add_path(path, item); (&mut *(self.0).0, self.1).read::() @@ -120,11 +121,12 @@ macro_rules! implOpenapiRouter { Handler::Body : 'static { let schema = (self.0).1.add_schema::(); + let id_schema = (self.0).1.add_schema::(); let body_schema = (self.0).1.add_schema::(); let path = format!("/{}/{{id}}", &self.1); let mut item = (self.0).1.remove_path(&path); - item.put = Some(OperationDescription::new::(schema).with_path_params(vec!["id"]).with_body::(body_schema).into_operation()); + item.put = Some(OperationDescription::new::(schema).add_path_param("id", id_schema).with_body::(body_schema).into_operation()); (self.0).1.add_path(path, item); (&mut *(self.0).0, self.1).update::() @@ -145,10 +147,11 @@ macro_rules! implOpenapiRouter { fn delete(&mut self) { let schema = (self.0).1.add_schema::(); + let id_schema = (self.0).1.add_schema::(); let path = format!("/{}/{{id}}", &self.1); let mut item = (self.0).1.remove_path(&path); - item.delete = Some(OperationDescription::new::(schema).with_path_params(vec!["id"]).into_operation()); + item.delete = Some(OperationDescription::new::(schema).add_path_param("id", id_schema).into_operation()); (self.0).1.add_path(path, item); (&mut *(self.0).0, self.1).delete::() diff --git a/gotham_restful/src/resource.rs b/gotham_restful/src/resource.rs index cd903b7..360f2a1 100644 --- a/gotham_restful/src/resource.rs +++ b/gotham_restful/src/resource.rs @@ -1,13 +1,11 @@ -use crate::{DrawResourceRoutes, RequestBody, ResourceResult, ResourceType}; +use crate::{DrawResourceRoutes, RequestBody, ResourceID, ResourceResult, ResourceType}; use gotham::{ extractor::QueryStringExtractor, hyper::Body, state::State }; -use serde::de::DeserializeOwned; use std::{ future::Future, - panic::RefUnwindSafe, pin::Pin }; @@ -48,7 +46,7 @@ pub trait ResourceReadAll : ResourceMethod /// Handle a GET request on the Resource with an id. pub trait ResourceRead : ResourceMethod { - type ID : DeserializeOwned + Clone + RefUnwindSafe + Send + Sync + 'static; + type ID : ResourceID + 'static; fn read(state : State, id : Self::ID) -> Pin + Send>>; } @@ -81,7 +79,7 @@ pub trait ResourceUpdateAll : ResourceMethod pub trait ResourceUpdate : ResourceMethod { 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 + Send>>; } @@ -95,7 +93,7 @@ pub trait ResourceDeleteAll : ResourceMethod /// Handle a DELETE request on the Resource with an id. pub trait ResourceDelete : ResourceMethod { - type ID : DeserializeOwned + Clone + RefUnwindSafe + Send + Sync + 'static; + type ID : ResourceID + 'static; fn delete(state : State, id : Self::ID) -> Pin + Send>>; } diff --git a/gotham_restful/src/types.rs b/gotham_restful/src/types.rs index d3a8e76..e0c769b 100644 --- a/gotham_restful/src/types.rs +++ b/gotham_restful/src/types.rs @@ -5,6 +5,7 @@ use crate::result::ResourceError; use gotham::hyper::body::Bytes; use mime::{Mime, APPLICATION_JSON}; use serde::{de::DeserializeOwned, Serialize}; +use std::panic::RefUnwindSafe; #[cfg(not(feature = "openapi"))] pub trait ResourceType @@ -78,3 +79,14 @@ impl RequestBody for T 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 ResourceID for T +{ +}