1
0
Fork 0
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:
Dominic 2019-10-20 00:36:00 +02:00
parent 9e9b8869c9
commit 3a03dc60fa
Signed by: msrd0
GPG key ID: DCC8C247452E98F9
2 changed files with 46 additions and 32 deletions

View file

@ -1,6 +1,7 @@
use crate::{ResourceType, StatusCode};
#[cfg(feature = "openapi")]
use crate::{OpenapiSchema, OpenapiType};
use hyper::Body;
use mime::{Mime, APPLICATION_JSON};
#[cfg(feature = "openapi")]
use openapiv3::{SchemaKind, StringFormat, StringType, Type, VariantOrUnknownOrEmpty};
@ -8,41 +9,54 @@ use serde::Serialize;
use serde_json::error::Error as SerdeJsonError;
use std::error::Error;
/// A response, used to create the final gotham response from.
pub struct Response
{
pub status : StatusCode,
pub body : String,
pub body : Body,
pub mime : Option<Mime>
}
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 {
status,
body,
body: body.into(),
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 {
status,
body,
body: body.into(),
mime: Some(APPLICATION_JSON)
}
}
/// Create a _204 No Content_ `Response`.
pub fn no_content() -> Self
{
Self {
status: StatusCode::NO_CONTENT,
body: String::new(),
body: Body::empty(),
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.
@ -50,7 +64,7 @@ pub trait ResourceResult
{
/// Turn this into a response that can be returned to the browser. This api will likely
/// 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.
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>
{
fn to_response(&self) -> Result<Response, SerdeJsonError>
fn into_response(self) -> Result<Response, SerdeJsonError>
{
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) => {
let err : ResourceError = e.into();
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>
{
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)?))
}
@ -208,7 +222,7 @@ impl From<()> for NoContent
impl ResourceResult for NoContent
{
/// 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())
}
@ -230,10 +244,10 @@ impl ResourceResult for NoContent
impl<E : Error> ResourceResult for Result<NoContent, E>
{
fn to_response(&self) -> Result<Response, SerdeJsonError>
fn into_response(self) -> Result<Response, SerdeJsonError>
{
match self {
Ok(nc) => nc.to_response(),
Ok(nc) => nc.into_response(),
Err(e) => {
let err : ResourceError = e.into();
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")]
@ -290,10 +304,10 @@ impl<T, E : Error> ResourceResult for Result<Raw<T>, E>
where
Raw<T> : ResourceResult
{
fn to_response(&self) -> Result<Response, SerdeJsonError>
fn into_response(self) -> Result<Response, SerdeJsonError>
{
match self {
Ok(raw) => raw.to_response(),
Ok(raw) => raw.into_response(),
Err(e) => {
let err : ResourceError = e.into();
Ok(Response::json(StatusCode::INTERNAL_SERVER_ERROR, serde_json::to_string(&err)?))
@ -331,50 +345,50 @@ mod test
fn resource_result_ok()
{
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.body, r#"{"msg":""}"#);
assert_eq!(res.mime, Some(APPLICATION_JSON));
assert_eq!(res.full_body(), r#"{"msg":""}"#.as_bytes());
}
#[test]
fn resource_result_err()
{
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.body, format!(r#"{{"error":true,"message":"{}"}}"#, err.unwrap_err()));
assert_eq!(res.mime, Some(APPLICATION_JSON));
assert_eq!(res.full_body(), format!(r#"{{"error":true,"message":"{}"}}"#, MsgError::default()).as_bytes());
}
#[test]
fn success_always_successfull()
{
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.body, r#"{"msg":""}"#);
assert_eq!(res.mime, Some(APPLICATION_JSON));
assert_eq!(res.full_body(), r#"{"msg":""}"#.as_bytes());
}
#[test]
fn no_content_has_empty_response()
{
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.body, "");
assert_eq!(res.mime, None);
assert_eq!(res.full_body(), &[] as &[u8]);
}
#[test]
fn no_content_result()
{
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.body, "");
assert_eq!(res.mime, None);
assert_eq!(res.full_body(), &[] as &[u8]);
}
#[test]
@ -382,9 +396,9 @@ mod test
{
let msg = "Test";
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.body, msg);
assert_eq!(res.mime, Some(TEXT_PLAIN));
assert_eq!(res.full_body(), msg.as_bytes());
}
}

View file

@ -131,7 +131,7 @@ where
F : FnOnce(&mut State) -> R,
R : ResourceResult
{
let res = get_result(&mut state).to_response();
let res = get_result(&mut state).into_response();
match res {
Ok(res) => {
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 {
Ok(res) => {
let r = response_from(res, &state);