mirror of
https://gitlab.com/msrd0/gotham-restful.git
synced 2025-04-19 22:44:38 +00:00
use Into<hyper::Body> for Response
This commit is contained in:
parent
9e9b8869c9
commit
3a03dc60fa
2 changed files with 46 additions and 32 deletions
|
@ -1,6 +1,7 @@
|
||||||
use crate::{ResourceType, StatusCode};
|
use crate::{ResourceType, StatusCode};
|
||||||
#[cfg(feature = "openapi")]
|
#[cfg(feature = "openapi")]
|
||||||
use crate::{OpenapiSchema, OpenapiType};
|
use crate::{OpenapiSchema, OpenapiType};
|
||||||
|
use hyper::Body;
|
||||||
use mime::{Mime, APPLICATION_JSON};
|
use mime::{Mime, APPLICATION_JSON};
|
||||||
#[cfg(feature = "openapi")]
|
#[cfg(feature = "openapi")]
|
||||||
use openapiv3::{SchemaKind, StringFormat, StringType, Type, VariantOrUnknownOrEmpty};
|
use openapiv3::{SchemaKind, StringFormat, StringType, Type, VariantOrUnknownOrEmpty};
|
||||||
|
@ -8,41 +9,54 @@ use serde::Serialize;
|
||||||
use serde_json::error::Error as SerdeJsonError;
|
use serde_json::error::Error as SerdeJsonError;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
|
||||||
|
/// A response, used to create the final gotham response from.
|
||||||
pub struct Response
|
pub struct Response
|
||||||
{
|
{
|
||||||
pub status : StatusCode,
|
pub status : StatusCode,
|
||||||
pub body : String,
|
pub body : Body,
|
||||||
pub mime : Option<Mime>
|
pub mime : Option<Mime>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Response
|
impl Response
|
||||||
{
|
{
|
||||||
pub fn new(status : StatusCode, body : String, mime : Option<Mime>) -> Self
|
/// Create a new `Response` from raw data.
|
||||||
|
pub fn new<B : Into<Body>>(status : StatusCode, body : B, mime : Option<Mime>) -> Self
|
||||||
{
|
{
|
||||||
Self {
|
Self {
|
||||||
status,
|
status,
|
||||||
body,
|
body: body.into(),
|
||||||
mime
|
mime
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn json(status : StatusCode, body : String) -> Self
|
/// Create a `Response` with mime type json from already serialized data.
|
||||||
|
pub fn json<B : Into<Body>>(status : StatusCode, body : B) -> Self
|
||||||
{
|
{
|
||||||
Self {
|
Self {
|
||||||
status,
|
status,
|
||||||
body,
|
body: body.into(),
|
||||||
mime: Some(APPLICATION_JSON)
|
mime: Some(APPLICATION_JSON)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create a _204 No Content_ `Response`.
|
||||||
pub fn no_content() -> Self
|
pub fn no_content() -> Self
|
||||||
{
|
{
|
||||||
Self {
|
Self {
|
||||||
status: StatusCode::NO_CONTENT,
|
status: StatusCode::NO_CONTENT,
|
||||||
body: String::new(),
|
body: Body::empty(),
|
||||||
mime: None
|
mime: None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
fn full_body(self) -> Vec<u8>
|
||||||
|
{
|
||||||
|
use futures::{future::Future, stream::Stream};
|
||||||
|
|
||||||
|
let bytes : &[u8] = &self.body.concat2().wait().unwrap().into_bytes();
|
||||||
|
bytes.to_vec()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A trait provided to convert a resource's result to json.
|
/// A trait provided to convert a resource's result to json.
|
||||||
|
@ -50,7 +64,7 @@ pub trait ResourceResult
|
||||||
{
|
{
|
||||||
/// Turn this into a response that can be returned to the browser. This api will likely
|
/// Turn this into a response that can be returned to the browser. This api will likely
|
||||||
/// change in the future.
|
/// change in the future.
|
||||||
fn to_response(&self) -> Result<Response, SerdeJsonError>;
|
fn into_response(self) -> Result<Response, SerdeJsonError>;
|
||||||
|
|
||||||
/// Return a list of supported mime types.
|
/// Return a list of supported mime types.
|
||||||
fn accepted_types() -> Option<Vec<Mime>>
|
fn accepted_types() -> Option<Vec<Mime>>
|
||||||
|
@ -98,10 +112,10 @@ impl<T : ToString> From<T> for ResourceError
|
||||||
|
|
||||||
impl<R : ResourceType, E : Error> ResourceResult for Result<R, E>
|
impl<R : ResourceType, E : Error> ResourceResult for Result<R, E>
|
||||||
{
|
{
|
||||||
fn to_response(&self) -> Result<Response, SerdeJsonError>
|
fn into_response(self) -> Result<Response, SerdeJsonError>
|
||||||
{
|
{
|
||||||
Ok(match self {
|
Ok(match self {
|
||||||
Ok(r) => Response::json(StatusCode::OK, serde_json::to_string(r)?),
|
Ok(r) => Response::json(StatusCode::OK, serde_json::to_string(&r)?),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
let err : ResourceError = e.into();
|
let err : ResourceError = e.into();
|
||||||
Response::json(StatusCode::INTERNAL_SERVER_ERROR, serde_json::to_string(&err)?)
|
Response::json(StatusCode::INTERNAL_SERVER_ERROR, serde_json::to_string(&err)?)
|
||||||
|
@ -158,7 +172,7 @@ impl<T> From<T> for Success<T>
|
||||||
|
|
||||||
impl<T : ResourceType> ResourceResult for Success<T>
|
impl<T : ResourceType> ResourceResult for Success<T>
|
||||||
{
|
{
|
||||||
fn to_response(&self) -> Result<Response, SerdeJsonError>
|
fn into_response(self) -> Result<Response, SerdeJsonError>
|
||||||
{
|
{
|
||||||
Ok(Response::json(StatusCode::OK, serde_json::to_string(&self.0)?))
|
Ok(Response::json(StatusCode::OK, serde_json::to_string(&self.0)?))
|
||||||
}
|
}
|
||||||
|
@ -208,7 +222,7 @@ impl From<()> for NoContent
|
||||||
impl ResourceResult for NoContent
|
impl ResourceResult for NoContent
|
||||||
{
|
{
|
||||||
/// This will always be a _204 No Content_ together with an empty string.
|
/// This will always be a _204 No Content_ together with an empty string.
|
||||||
fn to_response(&self) -> Result<Response, SerdeJsonError>
|
fn into_response(self) -> Result<Response, SerdeJsonError>
|
||||||
{
|
{
|
||||||
Ok(Response::no_content())
|
Ok(Response::no_content())
|
||||||
}
|
}
|
||||||
|
@ -230,10 +244,10 @@ impl ResourceResult for NoContent
|
||||||
|
|
||||||
impl<E : Error> ResourceResult for Result<NoContent, E>
|
impl<E : Error> ResourceResult for Result<NoContent, E>
|
||||||
{
|
{
|
||||||
fn to_response(&self) -> Result<Response, SerdeJsonError>
|
fn into_response(self) -> Result<Response, SerdeJsonError>
|
||||||
{
|
{
|
||||||
match self {
|
match self {
|
||||||
Ok(nc) => nc.to_response(),
|
Ok(nc) => nc.into_response(),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
let err : ResourceError = e.into();
|
let err : ResourceError = e.into();
|
||||||
Ok(Response::json(StatusCode::INTERNAL_SERVER_ERROR, serde_json::to_string(&err)?))
|
Ok(Response::json(StatusCode::INTERNAL_SERVER_ERROR, serde_json::to_string(&err)?))
|
||||||
|
@ -268,11 +282,11 @@ impl<T> Raw<T>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T : ToString> ResourceResult for Raw<T>
|
impl<T : Into<Body>> ResourceResult for Raw<T>
|
||||||
{
|
{
|
||||||
fn to_response(&self) -> Result<Response, SerdeJsonError>
|
fn into_response(self) -> Result<Response, SerdeJsonError>
|
||||||
{
|
{
|
||||||
Ok(Response::new(StatusCode::OK, self.raw.to_string(), Some(self.mime.clone())))
|
Ok(Response::new(StatusCode::OK, self.raw, Some(self.mime.clone())))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "openapi")]
|
#[cfg(feature = "openapi")]
|
||||||
|
@ -290,10 +304,10 @@ impl<T, E : Error> ResourceResult for Result<Raw<T>, E>
|
||||||
where
|
where
|
||||||
Raw<T> : ResourceResult
|
Raw<T> : ResourceResult
|
||||||
{
|
{
|
||||||
fn to_response(&self) -> Result<Response, SerdeJsonError>
|
fn into_response(self) -> Result<Response, SerdeJsonError>
|
||||||
{
|
{
|
||||||
match self {
|
match self {
|
||||||
Ok(raw) => raw.to_response(),
|
Ok(raw) => raw.into_response(),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
let err : ResourceError = e.into();
|
let err : ResourceError = e.into();
|
||||||
Ok(Response::json(StatusCode::INTERNAL_SERVER_ERROR, serde_json::to_string(&err)?))
|
Ok(Response::json(StatusCode::INTERNAL_SERVER_ERROR, serde_json::to_string(&err)?))
|
||||||
|
@ -331,50 +345,50 @@ mod test
|
||||||
fn resource_result_ok()
|
fn resource_result_ok()
|
||||||
{
|
{
|
||||||
let ok : Result<Msg, MsgError> = Ok(Msg::default());
|
let ok : Result<Msg, MsgError> = Ok(Msg::default());
|
||||||
let res = ok.to_response().expect("didn't expect error response");
|
let res = ok.into_response().expect("didn't expect error response");
|
||||||
assert_eq!(res.status, StatusCode::OK);
|
assert_eq!(res.status, StatusCode::OK);
|
||||||
assert_eq!(res.body, r#"{"msg":""}"#);
|
|
||||||
assert_eq!(res.mime, Some(APPLICATION_JSON));
|
assert_eq!(res.mime, Some(APPLICATION_JSON));
|
||||||
|
assert_eq!(res.full_body(), r#"{"msg":""}"#.as_bytes());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn resource_result_err()
|
fn resource_result_err()
|
||||||
{
|
{
|
||||||
let err : Result<Msg, MsgError> = Err(MsgError::default());
|
let err : Result<Msg, MsgError> = Err(MsgError::default());
|
||||||
let res = err.to_response().expect("didn't expect error response");
|
let res = err.into_response().expect("didn't expect error response");
|
||||||
assert_eq!(res.status, StatusCode::INTERNAL_SERVER_ERROR);
|
assert_eq!(res.status, StatusCode::INTERNAL_SERVER_ERROR);
|
||||||
assert_eq!(res.body, format!(r#"{{"error":true,"message":"{}"}}"#, err.unwrap_err()));
|
|
||||||
assert_eq!(res.mime, Some(APPLICATION_JSON));
|
assert_eq!(res.mime, Some(APPLICATION_JSON));
|
||||||
|
assert_eq!(res.full_body(), format!(r#"{{"error":true,"message":"{}"}}"#, MsgError::default()).as_bytes());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn success_always_successfull()
|
fn success_always_successfull()
|
||||||
{
|
{
|
||||||
let success : Success<Msg> = Msg::default().into();
|
let success : Success<Msg> = Msg::default().into();
|
||||||
let res = success.to_response().expect("didn't expect error response");
|
let res = success.into_response().expect("didn't expect error response");
|
||||||
assert_eq!(res.status, StatusCode::OK);
|
assert_eq!(res.status, StatusCode::OK);
|
||||||
assert_eq!(res.body, r#"{"msg":""}"#);
|
|
||||||
assert_eq!(res.mime, Some(APPLICATION_JSON));
|
assert_eq!(res.mime, Some(APPLICATION_JSON));
|
||||||
|
assert_eq!(res.full_body(), r#"{"msg":""}"#.as_bytes());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn no_content_has_empty_response()
|
fn no_content_has_empty_response()
|
||||||
{
|
{
|
||||||
let no_content = NoContent::default();
|
let no_content = NoContent::default();
|
||||||
let res = no_content.to_response().expect("didn't expect error response");
|
let res = no_content.into_response().expect("didn't expect error response");
|
||||||
assert_eq!(res.status, StatusCode::NO_CONTENT);
|
assert_eq!(res.status, StatusCode::NO_CONTENT);
|
||||||
assert_eq!(res.body, "");
|
|
||||||
assert_eq!(res.mime, None);
|
assert_eq!(res.mime, None);
|
||||||
|
assert_eq!(res.full_body(), &[] as &[u8]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn no_content_result()
|
fn no_content_result()
|
||||||
{
|
{
|
||||||
let no_content : Result<NoContent, MsgError> = Ok(NoContent::default());
|
let no_content : Result<NoContent, MsgError> = Ok(NoContent::default());
|
||||||
let res = no_content.to_response().expect("didn't expect error response");
|
let res = no_content.into_response().expect("didn't expect error response");
|
||||||
assert_eq!(res.status, StatusCode::NO_CONTENT);
|
assert_eq!(res.status, StatusCode::NO_CONTENT);
|
||||||
assert_eq!(res.body, "");
|
|
||||||
assert_eq!(res.mime, None);
|
assert_eq!(res.mime, None);
|
||||||
|
assert_eq!(res.full_body(), &[] as &[u8]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -382,9 +396,9 @@ mod test
|
||||||
{
|
{
|
||||||
let msg = "Test";
|
let msg = "Test";
|
||||||
let raw = Raw::new(msg, TEXT_PLAIN);
|
let raw = Raw::new(msg, TEXT_PLAIN);
|
||||||
let res = raw.to_response().expect("didn't expect error response");
|
let res = raw.into_response().expect("didn't expect error response");
|
||||||
assert_eq!(res.status, StatusCode::OK);
|
assert_eq!(res.status, StatusCode::OK);
|
||||||
assert_eq!(res.body, msg);
|
|
||||||
assert_eq!(res.mime, Some(TEXT_PLAIN));
|
assert_eq!(res.mime, Some(TEXT_PLAIN));
|
||||||
|
assert_eq!(res.full_body(), msg.as_bytes());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -131,7 +131,7 @@ where
|
||||||
F : FnOnce(&mut State) -> R,
|
F : FnOnce(&mut State) -> R,
|
||||||
R : ResourceResult
|
R : ResourceResult
|
||||||
{
|
{
|
||||||
let res = get_result(&mut state).to_response();
|
let res = get_result(&mut state).into_response();
|
||||||
match res {
|
match res {
|
||||||
Ok(res) => {
|
Ok(res) => {
|
||||||
let r = response_from(res, &state);
|
let r = response_from(res, &state);
|
||||||
|
@ -170,7 +170,7 @@ where
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let res = get_result(&mut state, body).to_response();
|
let res = get_result(&mut state, body).into_response();
|
||||||
match res {
|
match res {
|
||||||
Ok(res) => {
|
Ok(res) => {
|
||||||
let r = response_from(res, &state);
|
let r = response_from(res, &state);
|
||||||
|
|
Loading…
Add table
Reference in a new issue