1
0
Fork 0
mirror of https://gitlab.com/msrd0/gotham-restful.git synced 2025-04-20 06:54:46 +00:00

update to gotham 0.5 and start using rustfmt

This commit is contained in:
Dominic 2020-09-15 15:10:41 +02:00
parent 5317e50961
commit d55b0897e9
Signed by: msrd0
GPG key ID: DCC8C247452E98F9
39 changed files with 1798 additions and 2095 deletions

View file

@ -1,6 +1,5 @@
use gotham_restful_derive::ResourceError;
/**
This is an error type that always yields a _403 Forbidden_ response. This type is best used in
combination with [`AuthSuccess`] or [`AuthResult`].
@ -9,8 +8,7 @@ combination with [`AuthSuccess`] or [`AuthResult`].
[`AuthResult`]: type.AuthResult.html
*/
#[derive(Debug, Clone, Copy, ResourceError)]
pub enum AuthError
{
pub enum AuthError {
#[status(FORBIDDEN)]
#[display("Forbidden")]
Forbidden
@ -57,8 +55,7 @@ error, or delegates to another error type. This type is best used with [`AuthRes
[`AuthResult`]: type.AuthResult.html
*/
#[derive(Debug, ResourceError)]
pub enum AuthErrorOrOther<E>
{
pub enum AuthErrorOrOther<E> {
#[status(FORBIDDEN)]
#[display("Forbidden")]
Forbidden,
@ -67,10 +64,8 @@ pub enum AuthErrorOrOther<E>
Other(E)
}
impl<E> From<AuthError> for AuthErrorOrOther<E>
{
fn from(err : AuthError) -> Self
{
impl<E> From<AuthError> for AuthErrorOrOther<E> {
fn from(err: AuthError) -> Self {
match err {
AuthError::Forbidden => Self::Forbidden
}
@ -80,10 +75,9 @@ impl<E> From<AuthError> for AuthErrorOrOther<E>
impl<E, F> From<F> for AuthErrorOrOther<E>
where
// TODO https://gitlab.com/msrd0/gotham-restful/-/issues/20
F : std::error::Error + Into<E>
F: std::error::Error + Into<E>
{
fn from(err : F) -> Self
{
fn from(err: F) -> Self {
Self::Other(err.into())
}
}

View file

@ -1,13 +1,13 @@
use crate::Response;
#[cfg(feature = "openapi")]
use crate::OpenapiSchema;
use crate::Response;
use futures_util::future::FutureExt;
use mime::{Mime, STAR_STAR};
use serde::Serialize;
use std::{
error::Error,
future::Future,
fmt::{Debug, Display},
future::Future,
pin::Pin
};
@ -27,67 +27,54 @@ pub use result::IntoResponseError;
mod success;
pub use success::Success;
pub(crate) trait OrAllTypes
{
pub(crate) trait OrAllTypes {
fn or_all_types(self) -> Vec<Mime>;
}
impl OrAllTypes for Option<Vec<Mime>>
{
fn or_all_types(self) -> Vec<Mime>
{
impl OrAllTypes for Option<Vec<Mime>> {
fn or_all_types(self) -> Vec<Mime> {
self.unwrap_or_else(|| vec![STAR_STAR])
}
}
/// A trait provided to convert a resource's result to json.
pub trait ResourceResult
{
type Err : Error + Send + 'static;
pub trait ResourceResult {
type Err: Error + Send + Sync + 'static;
/// Turn this into a response that can be returned to the browser. This api will likely
/// change in the future.
fn into_response(self) -> Pin<Box<dyn Future<Output = Result<Response, Self::Err>> + Send>>;
/// Return a list of supported mime types.
fn accepted_types() -> Option<Vec<Mime>>
{
fn accepted_types() -> Option<Vec<Mime>> {
None
}
#[cfg(feature = "openapi")]
fn schema() -> OpenapiSchema;
#[cfg(feature = "openapi")]
fn default_status() -> crate::StatusCode
{
fn default_status() -> crate::StatusCode {
crate::StatusCode::OK
}
}
#[cfg(feature = "openapi")]
impl<Res : ResourceResult> crate::OpenapiType for Res
{
fn schema() -> OpenapiSchema
{
impl<Res: ResourceResult> crate::OpenapiType for Res {
fn schema() -> OpenapiSchema {
Self::schema()
}
}
/// The default json returned on an 500 Internal Server Error.
#[derive(Debug, Serialize)]
pub(crate) struct ResourceError
{
error : bool,
message : String
pub(crate) struct ResourceError {
error: bool,
message: String
}
impl<T : ToString> From<T> for ResourceError
{
fn from(message : T) -> Self
{
impl<T: ToString> From<T> for ResourceError {
fn from(message: T) -> Self {
Self {
error: true,
message: message.to_string()
@ -95,27 +82,26 @@ impl<T : ToString> From<T> for ResourceError
}
}
fn into_response_helper<Err, F>(create_response : F) -> Pin<Box<dyn Future<Output = Result<Response, Err>> + Send>>
fn into_response_helper<Err, F>(create_response: F) -> Pin<Box<dyn Future<Output = Result<Response, Err>> + Send>>
where
Err : Send + 'static,
F : FnOnce() -> Result<Response, Err>
Err: Send + 'static,
F: FnOnce() -> Result<Response, Err>
{
let res = create_response();
async move { res }.boxed()
}
#[cfg(feature = "errorlog")]
fn errorlog<E : Display>(e : E)
{
fn errorlog<E: Display>(e: E) {
error!("The handler encountered an error: {}", e);
}
#[cfg(not(feature = "errorlog"))]
fn errorlog<E>(_e : E) {}
fn errorlog<E>(_e: E) {}
fn handle_error<E>(e : E) -> Pin<Box<dyn Future<Output = Result<Response, E::Err>> + Send>>
fn handle_error<E>(e: E) -> Pin<Box<dyn Future<Output = Result<Response, E::Err>> + Send>>
where
E : Display + IntoResponseError
E: Display + IntoResponseError
{
into_response_helper(|| {
errorlog(&e);
@ -123,67 +109,55 @@ where
})
}
impl<Res> ResourceResult for Pin<Box<dyn Future<Output = Res> + Send>>
where
Res : ResourceResult + 'static
Res: ResourceResult + 'static
{
type Err = Res::Err;
fn into_response(self) -> Pin<Box<dyn Future<Output = Result<Response, Self::Err>> + Send>>
{
self.then(|result| {
result.into_response()
}).boxed()
fn into_response(self) -> Pin<Box<dyn Future<Output = Result<Response, Self::Err>> + Send>> {
self.then(|result| result.into_response()).boxed()
}
fn accepted_types() -> Option<Vec<Mime>>
{
fn accepted_types() -> Option<Vec<Mime>> {
Res::accepted_types()
}
#[cfg(feature = "openapi")]
fn schema() -> OpenapiSchema
{
fn schema() -> OpenapiSchema {
Res::schema()
}
#[cfg(feature = "openapi")]
fn default_status() -> crate::StatusCode
{
fn default_status() -> crate::StatusCode {
Res::default_status()
}
}
#[cfg(test)]
mod test
{
mod test {
use super::*;
use futures_executor::block_on;
use thiserror::Error;
#[derive(Debug, Default, Deserialize, Serialize)]
#[cfg_attr(feature = "openapi", derive(crate::OpenapiType))]
struct Msg
{
msg : String
struct Msg {
msg: String
}
#[derive(Debug, Default, Error)]
#[error("An Error")]
struct MsgError;
#[test]
fn result_from_future()
{
fn result_from_future() {
let nc = NoContent::default();
let res = block_on(nc.into_response()).unwrap();
let fut_nc = async move { NoContent::default() }.boxed();
let fut_res = block_on(fut_nc.into_response()).unwrap();
assert_eq!(res.status, fut_res.status);
assert_eq!(res.mime, fut_res.mime);
assert_eq!(res.full_body().unwrap(), fut_res.full_body().unwrap());

View file

@ -1,14 +1,10 @@
use super::{ResourceResult, handle_error};
use super::{handle_error, ResourceResult};
use crate::{IntoResponseError, Response};
#[cfg(feature = "openapi")]
use crate::{OpenapiSchema, OpenapiType};
use futures_util::{future, future::FutureExt};
use mime::Mime;
use std::{
fmt::Display,
future::Future,
pin::Pin
};
use std::{fmt::Display, future::Future, pin::Pin};
/**
This is the return type of a resource that doesn't actually return something. It will result
@ -35,104 +31,89 @@ fn read_all(_state: &mut State) {
#[derive(Clone, Copy, Debug, Default)]
pub struct NoContent;
impl From<()> for NoContent
{
fn from(_ : ()) -> Self
{
impl From<()> for NoContent {
fn from(_: ()) -> Self {
Self {}
}
}
impl ResourceResult for NoContent
{
impl ResourceResult for NoContent {
// TODO this shouldn't be a serde_json::Error
type Err = serde_json::Error; // just for easier handling of `Result<NoContent, E>`
/// This will always be a _204 No Content_ together with an empty string.
fn into_response(self) -> Pin<Box<dyn Future<Output = Result<Response, Self::Err>> + Send>>
{
fn into_response(self) -> Pin<Box<dyn Future<Output = Result<Response, Self::Err>> + Send>> {
future::ok(Response::no_content()).boxed()
}
fn accepted_types() -> Option<Vec<Mime>>
{
fn accepted_types() -> Option<Vec<Mime>> {
Some(Vec::new())
}
/// Returns the schema of the `()` type.
#[cfg(feature = "openapi")]
fn schema() -> OpenapiSchema
{
fn schema() -> OpenapiSchema {
<()>::schema()
}
/// This will always be a _204 No Content_
#[cfg(feature = "openapi")]
fn default_status() -> crate::StatusCode
{
fn default_status() -> crate::StatusCode {
crate::StatusCode::NO_CONTENT
}
}
impl<E> ResourceResult for Result<NoContent, E>
where
E : Display + IntoResponseError<Err = serde_json::Error>
E: Display + IntoResponseError<Err = serde_json::Error>
{
type Err = serde_json::Error;
fn into_response(self) -> Pin<Box<dyn Future<Output = Result<Response, serde_json::Error>> + Send>>
{
fn into_response(self) -> Pin<Box<dyn Future<Output = Result<Response, serde_json::Error>> + Send>> {
match self {
Ok(nc) => nc.into_response(),
Err(e) => handle_error(e)
}
}
fn accepted_types() -> Option<Vec<Mime>>
{
fn accepted_types() -> Option<Vec<Mime>> {
NoContent::accepted_types()
}
#[cfg(feature = "openapi")]
fn schema() -> OpenapiSchema
{
fn schema() -> OpenapiSchema {
<NoContent as ResourceResult>::schema()
}
#[cfg(feature = "openapi")]
fn default_status() -> crate::StatusCode
{
fn default_status() -> crate::StatusCode {
NoContent::default_status()
}
}
#[cfg(test)]
mod test
{
mod test {
use super::*;
use futures_executor::block_on;
use gotham::hyper::StatusCode;
use thiserror::Error;
#[derive(Debug, Default, Error)]
#[error("An Error")]
struct MsgError;
#[test]
fn no_content_has_empty_response()
{
fn no_content_has_empty_response() {
let no_content = NoContent::default();
let res = block_on(no_content.into_response()).expect("didn't expect error response");
assert_eq!(res.status, StatusCode::NO_CONTENT);
assert_eq!(res.mime, None);
assert_eq!(res.full_body().unwrap(), &[] as &[u8]);
}
#[test]
fn no_content_result()
{
let no_content : Result<NoContent, MsgError> = Ok(NoContent::default());
fn no_content_result() {
let no_content: Result<NoContent, MsgError> = Ok(NoContent::default());
let res = block_on(no_content.into_response()).expect("didn't expect error response");
assert_eq!(res.status, StatusCode::NO_CONTENT);
assert_eq!(res.mime, None);

View file

@ -1,7 +1,7 @@
use super::{IntoResponseError, ResourceResult, handle_error};
use crate::{FromBody, RequestBody, ResourceType, Response, StatusCode};
use super::{handle_error, IntoResponseError, ResourceResult};
#[cfg(feature = "openapi")]
use crate::OpenapiSchema;
use crate::{FromBody, RequestBody, ResourceType, Response, StatusCode};
use futures_core::future::Future;
use futures_util::{future, future::FutureExt};
use gotham::hyper::body::{Body, Bytes};
@ -9,11 +9,7 @@ use mime::Mime;
#[cfg(feature = "openapi")]
use openapiv3::{SchemaKind, StringFormat, StringType, Type, VariantOrUnknownOrEmpty};
use serde_json::error::Error as SerdeJsonError;
use std::{
convert::Infallible,
fmt::Display,
pin::Pin
};
use std::{convert::Infallible, fmt::Display, pin::Pin};
/**
This type can be used both as a raw request body, as well as as a raw response. However, all types
@ -43,44 +39,37 @@ fn create(body : Raw<Vec<u8>>) -> Raw<Vec<u8>> {
[`OpenapiType`]: trait.OpenapiType.html
*/
#[derive(Debug)]
pub struct Raw<T>
{
pub raw : T,
pub mime : Mime
pub struct Raw<T> {
pub raw: T,
pub mime: Mime
}
impl<T> Raw<T>
{
pub fn new(raw : T, mime : Mime) -> Self
{
impl<T> Raw<T> {
pub fn new(raw: T, mime: Mime) -> Self {
Self { raw, mime }
}
}
impl<T, U> AsMut<U> for Raw<T>
where
T : AsMut<U>
T: AsMut<U>
{
fn as_mut(&mut self) -> &mut U
{
fn as_mut(&mut self) -> &mut U {
self.raw.as_mut()
}
}
impl<T, U> AsRef<U> for Raw<T>
where
T : AsRef<U>
T: AsRef<U>
{
fn as_ref(&self) -> &U
{
fn as_ref(&self) -> &U {
self.raw.as_ref()
}
}
impl<T : Clone> Clone for Raw<T>
{
fn clone(&self) -> Self
{
impl<T: Clone> Clone for Raw<T> {
fn clone(&self) -> Self {
Self {
raw: self.raw.clone(),
mime: self.mime.clone()
@ -88,36 +77,28 @@ impl<T : Clone> Clone for Raw<T>
}
}
impl<T : for<'a> From<&'a [u8]>> FromBody for Raw<T>
{
impl<T: for<'a> From<&'a [u8]>> FromBody for Raw<T> {
type Err = Infallible;
fn from_body(body : Bytes, mime : Mime) -> Result<Self, Self::Err>
{
fn from_body(body: Bytes, mime: Mime) -> Result<Self, Self::Err> {
Ok(Self::new(body.as_ref().into(), mime))
}
}
impl<T> RequestBody for Raw<T>
where
Raw<T> : FromBody + ResourceType
{
}
impl<T> RequestBody for Raw<T> where Raw<T>: FromBody + ResourceType {}
impl<T : Into<Body>> ResourceResult for Raw<T>
impl<T: Into<Body>> ResourceResult for Raw<T>
where
Self : Send
Self: Send
{
type Err = SerdeJsonError; // just for easier handling of `Result<Raw<T>, E>`
fn into_response(self) -> Pin<Box<dyn Future<Output = Result<Response, SerdeJsonError>> + Send>>
{
fn into_response(self) -> Pin<Box<dyn Future<Output = Result<Response, SerdeJsonError>> + Send>> {
future::ok(Response::new(StatusCode::OK, self.raw, Some(self.mime.clone()))).boxed()
}
#[cfg(feature = "openapi")]
fn schema() -> OpenapiSchema
{
fn schema() -> OpenapiSchema {
OpenapiSchema::new(SchemaKind::Type(Type::String(StringType {
format: VariantOrUnknownOrEmpty::Item(StringFormat::Binary),
..Default::default()
@ -127,37 +108,32 @@ where
impl<T, E> ResourceResult for Result<Raw<T>, E>
where
Raw<T> : ResourceResult,
E : Display + IntoResponseError<Err = <Raw<T> as ResourceResult>::Err>
Raw<T>: ResourceResult,
E: Display + IntoResponseError<Err = <Raw<T> as ResourceResult>::Err>
{
type Err = E::Err;
fn into_response(self) -> Pin<Box<dyn Future<Output = Result<Response, E::Err>> + Send>>
{
fn into_response(self) -> Pin<Box<dyn Future<Output = Result<Response, E::Err>> + Send>> {
match self {
Ok(raw) => raw.into_response(),
Err(e) => handle_error(e)
}
}
#[cfg(feature = "openapi")]
fn schema() -> OpenapiSchema
{
fn schema() -> OpenapiSchema {
<Raw<T> as ResourceResult>::schema()
}
}
#[cfg(test)]
mod test
{
mod test {
use super::*;
use futures_executor::block_on;
use mime::TEXT_PLAIN;
#[test]
fn raw_response()
{
fn raw_response() {
let msg = "Test";
let raw = Raw::new(msg, TEXT_PLAIN);
let res = block_on(raw.into_response()).expect("didn't expect error response");

View file

@ -1,106 +1,95 @@
use super::{ResourceResult, handle_error, into_response_helper};
use crate::{
result::ResourceError,
Response, ResponseBody, StatusCode
};
use super::{handle_error, into_response_helper, ResourceResult};
#[cfg(feature = "openapi")]
use crate::OpenapiSchema;
use crate::{result::ResourceError, Response, ResponseBody, StatusCode};
use futures_core::future::Future;
use mime::{Mime, APPLICATION_JSON};
use std::{
error::Error,
fmt::Display,
pin::Pin
};
use std::{error::Error, fmt::Display, pin::Pin};
pub trait IntoResponseError {
type Err: Error + Send + 'static;
pub trait IntoResponseError
{
type Err : Error + Send + 'static;
fn into_response_error(self) -> Result<Response, Self::Err>;
}
impl<E : Error> IntoResponseError for E
{
impl<E: Error> IntoResponseError for E {
type Err = serde_json::Error;
fn into_response_error(self) -> Result<Response, Self::Err>
{
let err : ResourceError = self.into();
Ok(Response::json(StatusCode::INTERNAL_SERVER_ERROR, serde_json::to_string(&err)?))
fn into_response_error(self) -> Result<Response, Self::Err> {
let err: ResourceError = self.into();
Ok(Response::json(
StatusCode::INTERNAL_SERVER_ERROR,
serde_json::to_string(&err)?
))
}
}
impl<R, E> ResourceResult for Result<R, E>
where
R : ResponseBody,
E : Display + IntoResponseError<Err = serde_json::Error>
R: ResponseBody,
E: Display + IntoResponseError<Err = serde_json::Error>
{
type Err = E::Err;
fn into_response(self) -> Pin<Box<dyn Future<Output = Result<Response, E::Err>> + Send>>
{
fn into_response(self) -> Pin<Box<dyn Future<Output = Result<Response, E::Err>> + Send>> {
match self {
Ok(r) => into_response_helper(|| Ok(Response::json(StatusCode::OK, serde_json::to_string(&r)?))),
Err(e) => handle_error(e)
}
}
fn accepted_types() -> Option<Vec<Mime>>
{
fn accepted_types() -> Option<Vec<Mime>> {
Some(vec![APPLICATION_JSON])
}
#[cfg(feature = "openapi")]
fn schema() -> OpenapiSchema
{
fn schema() -> OpenapiSchema {
R::schema()
}
}
#[cfg(test)]
mod test
{
mod test {
use super::*;
use crate::result::OrAllTypes;
use futures_executor::block_on;
use thiserror::Error;
#[derive(Debug, Default, Deserialize, Serialize)]
#[cfg_attr(feature = "openapi", derive(crate::OpenapiType))]
struct Msg
{
msg : String
struct Msg {
msg: String
}
#[derive(Debug, Default, Error)]
#[error("An Error")]
struct MsgError;
#[test]
fn result_ok()
{
let ok : Result<Msg, MsgError> = Ok(Msg::default());
fn result_ok() {
let ok: Result<Msg, MsgError> = Ok(Msg::default());
let res = block_on(ok.into_response()).expect("didn't expect error response");
assert_eq!(res.status, StatusCode::OK);
assert_eq!(res.mime, Some(APPLICATION_JSON));
assert_eq!(res.full_body().unwrap(), r#"{"msg":""}"#.as_bytes());
}
#[test]
fn result_err()
{
let err : Result<Msg, MsgError> = Err(MsgError::default());
fn result_err() {
let err: Result<Msg, MsgError> = Err(MsgError::default());
let res = block_on(err.into_response()).expect("didn't expect error response");
assert_eq!(res.status, StatusCode::INTERNAL_SERVER_ERROR);
assert_eq!(res.mime, Some(APPLICATION_JSON));
assert_eq!(res.full_body().unwrap(), format!(r#"{{"error":true,"message":"{}"}}"#, MsgError::default()).as_bytes());
assert_eq!(
res.full_body().unwrap(),
format!(r#"{{"error":true,"message":"{}"}}"#, MsgError::default()).as_bytes()
);
}
#[test]
fn success_accepts_json()
{
assert!(<Result<Msg, MsgError>>::accepted_types().or_all_types().contains(&APPLICATION_JSON))
fn success_accepts_json() {
assert!(<Result<Msg, MsgError>>::accepted_types()
.or_all_types()
.contains(&APPLICATION_JSON))
}
}

View file

@ -1,14 +1,14 @@
use super::{ResourceResult, into_response_helper};
use crate::{Response, ResponseBody};
use super::{into_response_helper, ResourceResult};
#[cfg(feature = "openapi")]
use crate::OpenapiSchema;
use crate::{Response, ResponseBody};
use gotham::hyper::StatusCode;
use mime::{Mime, APPLICATION_JSON};
use std::{
fmt::Debug,
future::Future,
pin::Pin,
ops::{Deref, DerefMut}
ops::{Deref, DerefMut},
pin::Pin
};
/**
@ -45,119 +45,95 @@ fn read_all(_state: &mut State) -> Success<MyResponse> {
#[derive(Debug)]
pub struct Success<T>(T);
impl<T> AsMut<T> for Success<T>
{
fn as_mut(&mut self) -> &mut T
{
impl<T> AsMut<T> for Success<T> {
fn as_mut(&mut self) -> &mut T {
&mut self.0
}
}
impl<T> AsRef<T> for Success<T>
{
fn as_ref(&self) -> &T
{
impl<T> AsRef<T> for Success<T> {
fn as_ref(&self) -> &T {
&self.0
}
}
impl<T> Deref for Success<T>
{
impl<T> Deref for Success<T> {
type Target = T;
fn deref(&self) -> &T
{
fn deref(&self) -> &T {
&self.0
}
}
impl<T> DerefMut for Success<T>
{
fn deref_mut(&mut self) -> &mut T
{
impl<T> DerefMut for Success<T> {
fn deref_mut(&mut self) -> &mut T {
&mut self.0
}
}
impl<T> From<T> for Success<T>
{
fn from(t : T) -> Self
{
impl<T> From<T> for Success<T> {
fn from(t: T) -> Self {
Self(t)
}
}
impl<T : Clone> Clone for Success<T>
{
fn clone(&self) -> Self
{
impl<T: Clone> Clone for Success<T> {
fn clone(&self) -> Self {
Self(self.0.clone())
}
}
impl<T : Copy> Copy for Success<T>
{
}
impl<T: Copy> Copy for Success<T> {}
impl<T : Default> Default for Success<T>
{
fn default() -> Self
{
impl<T: Default> Default for Success<T> {
fn default() -> Self {
Self(T::default())
}
}
impl<T : ResponseBody> ResourceResult for Success<T>
impl<T: ResponseBody> ResourceResult for Success<T>
where
Self : Send
Self: Send
{
type Err = serde_json::Error;
fn into_response(self) -> Pin<Box<dyn Future<Output = Result<Response, Self::Err>> + Send>>
{
fn into_response(self) -> Pin<Box<dyn Future<Output = Result<Response, Self::Err>> + Send>> {
into_response_helper(|| Ok(Response::json(StatusCode::OK, serde_json::to_string(self.as_ref())?)))
}
fn accepted_types() -> Option<Vec<Mime>>
{
fn accepted_types() -> Option<Vec<Mime>> {
Some(vec![APPLICATION_JSON])
}
#[cfg(feature = "openapi")]
fn schema() -> OpenapiSchema
{
fn schema() -> OpenapiSchema {
T::schema()
}
}
#[cfg(test)]
mod test
{
mod test {
use super::*;
use crate::result::OrAllTypes;
use futures_executor::block_on;
#[derive(Debug, Default, Serialize)]
#[cfg_attr(feature = "openapi", derive(crate::OpenapiType))]
struct Msg
{
msg : String
struct Msg {
msg: String
}
#[test]
fn success_always_successfull()
{
let success : Success<Msg> = Msg::default().into();
fn success_always_successfull() {
let success: Success<Msg> = Msg::default().into();
let res = block_on(success.into_response()).expect("didn't expect error response");
assert_eq!(res.status, StatusCode::OK);
assert_eq!(res.mime, Some(APPLICATION_JSON));
assert_eq!(res.full_body().unwrap(), r#"{"msg":""}"#.as_bytes());
}
#[test]
fn success_accepts_json()
{
fn success_accepts_json() {
assert!(<Success<Msg>>::accepted_types().or_all_types().contains(&APPLICATION_JSON))
}
}