diff --git a/example/src/main.rs b/example/src/main.rs index fc7c3a3..507b27c 100644 --- a/example/src/main.rs +++ b/example/src/main.rs @@ -49,35 +49,35 @@ fn read(_state : &mut State, id : u64) -> Success } #[rest_create(Users)] -fn create(_state : &mut State, body : User) -> Success<()> +fn create(_state : &mut State, body : User) -> NoContent { info!("Created User: {}", body.username); ().into() } #[rest_update_all(Users)] -fn update_all(_state : &mut State, body : Vec) -> Success<()> +fn update_all(_state : &mut State, body : Vec) -> NoContent { info!("Changing all Users to {:?}", body.into_iter().map(|u| u.username).collect::>()); ().into() } #[rest_update(Users)] -fn update(_state : &mut State, id : u64, body : User) -> Success<()> +fn update(_state : &mut State, id : u64, body : User) -> NoContent { info!("Change User {} to {}", id, body.username); ().into() } #[rest_delete_all(Users)] -fn delete_all(_state : &mut State) -> Success<()> +fn delete_all(_state : &mut State) -> NoContent { info!("Delete all Users"); ().into() } #[rest_delete(Users)] -fn delete(_state : &mut State, id : u64) -> Success<()> +fn delete(_state : &mut State, id : u64) -> NoContent { info!("Delete User {}", id); ().into() diff --git a/gotham_restful/src/lib.rs b/gotham_restful/src/lib.rs index 470d119..d90d932 100644 --- a/gotham_restful/src/lib.rs +++ b/gotham_restful/src/lib.rs @@ -27,7 +27,11 @@ pub use resource::{ }; mod result; -pub use result::{ResourceResult, Success}; +pub use result::{ + NoContent, + ResourceResult, + Success +}; mod routing; pub use routing::{DrawResources, DrawResourceRoutes}; diff --git a/gotham_restful/src/openapi/router.rs b/gotham_restful/src/openapi/router.rs index bc9cb60..1d89eb9 100644 --- a/gotham_restful/src/openapi/router.rs +++ b/gotham_restful/src/openapi/router.rs @@ -175,13 +175,18 @@ fn schema_to_content(schema : ReferenceOr) -> IndexMap, path_params : Vec<&str>, body_schema : Option>) -> Operation +fn new_operation(default_status : hyper::StatusCode, schema : ReferenceOr, path_params : Vec<&str>, body_schema : Option>) -> Operation { + let content = match default_status.as_u16() { + 204 => IndexMap::new(), + _ => schema_to_content(schema) + }; + let mut responses : IndexMap> = IndexMap::new(); - responses.insert(StatusCode::Code(200), Item(Response { - description: "OK".to_string(), + responses.insert(StatusCode::Code(default_status.as_u16()), Item(Response { + description: default_status.canonical_reason().map(|d| d.to_string()).unwrap_or_default(), headers: IndexMap::new(), - content: schema_to_content(schema), + content, links: IndexMap::new() })); @@ -265,7 +270,7 @@ macro_rules! implOpenapiRouter { let path = format!("/{}", &self.1); let mut item = (self.0).1.remove_path(&path); - item.get = Some(new_operation(schema, vec![], None)); + item.get = Some(new_operation(Res::default_status(), schema, vec![], None)); (self.0).1.add_path(path, item); (&mut *(self.0).0, self.1.to_string()).read_all::() @@ -281,7 +286,7 @@ macro_rules! implOpenapiRouter { let path = format!("/{}/{{id}}", &self.1); let mut item = (self.0).1.remove_path(&path); - item.get = Some(new_operation(schema, vec!["id"], None)); + item.get = Some(new_operation(Res::default_status(), schema, vec!["id"], None)); (self.0).1.add_path(path, item); (&mut *(self.0).0, self.1.to_string()).read::() @@ -298,7 +303,7 @@ macro_rules! implOpenapiRouter { let path = format!("/{}", &self.1); let mut item = (self.0).1.remove_path(&path); - item.post = Some(new_operation(schema, vec![], Some(body_schema))); + item.post = Some(new_operation(Res::default_status(), schema, vec![], Some(body_schema))); (self.0).1.add_path(path, item); (&mut *(self.0).0, self.1.to_string()).create::() @@ -315,7 +320,7 @@ macro_rules! implOpenapiRouter { let path = format!("/{}", &self.1); let mut item = (self.0).1.remove_path(&path); - item.put = Some(new_operation(schema, vec![], Some(body_schema))); + item.put = Some(new_operation(Res::default_status(), schema, vec![], Some(body_schema))); (self.0).1.add_path(path, item); (&mut *(self.0).0, self.1.to_string()).update_all::() @@ -333,7 +338,7 @@ macro_rules! implOpenapiRouter { let path = format!("/{}/{{id}}", &self.1); let mut item = (self.0).1.remove_path(&path); - item.put = Some(new_operation(schema, vec!["id"], Some(body_schema))); + item.put = Some(new_operation(Res::default_status(), schema, vec!["id"], Some(body_schema))); (self.0).1.add_path(path, item); (&mut *(self.0).0, self.1.to_string()).update::() @@ -348,7 +353,7 @@ macro_rules! implOpenapiRouter { let path = format!("/{}", &self.1); let mut item = (self.0).1.remove_path(&path); - item.delete = Some(new_operation(schema, vec![], None)); + item.delete = Some(new_operation(Res::default_status(), schema, vec![], None)); (self.0).1.add_path(path, item); (&mut *(self.0).0, self.1.to_string()).delete_all::() @@ -364,7 +369,7 @@ macro_rules! implOpenapiRouter { let path = format!("/{}/{{id}}", &self.1); let mut item = (self.0).1.remove_path(&path); - item.delete = Some(new_operation(schema, vec!["id"], None)); + item.delete = Some(new_operation(Res::default_status(), schema, vec!["id"], None)); (self.0).1.add_path(path, item); (&mut *(self.0).0, self.1.to_string()).delete::() diff --git a/gotham_restful/src/result.rs b/gotham_restful/src/result.rs index b73bee5..9f84d54 100644 --- a/gotham_restful/src/result.rs +++ b/gotham_restful/src/result.rs @@ -1,6 +1,6 @@ use crate::{ResourceType, StatusCode}; #[cfg(feature = "openapi")] -use crate::OpenapiSchema; +use crate::{OpenapiSchema, OpenapiType}; use serde::Serialize; use serde_json::error::Error as SerdeJsonError; use std::error::Error; @@ -12,6 +12,12 @@ pub trait ResourceResult #[cfg(feature = "openapi")] fn to_schema() -> OpenapiSchema; + + #[cfg(feature = "openapi")] + fn default_status() -> StatusCode + { + StatusCode::OK + } } #[cfg(feature = "openapi")] @@ -86,3 +92,34 @@ impl ResourceResult for Success T::to_schema() } } + +/// This can be returned from a resource when there is no content to send. +pub struct NoContent; + +impl From<()> for NoContent +{ + fn from(_ : ()) -> Self + { + Self {} + } +} + +impl ResourceResult for NoContent +{ + fn to_json(&self) -> Result<(StatusCode, String), SerdeJsonError> + { + Ok((StatusCode::NO_CONTENT, "".to_string())) + } + + #[cfg(feature = "openapi")] + fn to_schema() -> OpenapiSchema + { + <()>::to_schema() + } + + #[cfg(feature = "openapi")] + fn default_status() -> StatusCode + { + StatusCode::NO_CONTENT + } +}