1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
extern crate failure; extern crate futures; extern crate gotham; extern crate hyper; extern crate mime; extern crate serde; extern crate serde_json; use failure::Error; use futures::{Future, Stream}; use gotham::handler::{HandlerError, IntoHandlerError}; use gotham::http::response::create_response; use gotham::state::{FromState, State}; use hyper::{Body, Response, StatusCode}; use serde::de::DeserializeOwned; use serde::Serialize; use serde_json::{from_str, to_string}; pub trait JSONBody { fn json<'de, T: 'de>( self, ) -> Box<Future<Item = (State, T), Error = (State, HandlerError)> + 'de> where T: DeserializeOwned; } impl JSONBody for State { fn json<'de, T: 'de>( mut self, ) -> Box<Future<Item = (State, T), Error = (State, HandlerError)> + 'de> where T: DeserializeOwned, { let body = Body::take_from(&mut self); let f = body.concat2() .map_err(|err| Error::from(err)) .then(|res| match res { Ok(body) => { let json = String::from_utf8(body.to_vec()).unwrap(); match from_str(&json) { Ok(parsed) => Ok((self, parsed)), Err(err) => Err((self, Error::from(err))), } } Err(err) => Err((self, err)), }) .map_err(|(state, err)| { ( state, HandlerError::with_status( err.compat().into_handler_error(), StatusCode::UnprocessableEntity, ), ) }); Box::new(f) } } pub fn create_json_response<S: Serialize>( state: &State, status: StatusCode, data: &S, ) -> Result<Response, serde_json::Error> { to_string(data).map(|json_str| { create_response( state, status, Some((json_str.into_bytes(), mime::APPLICATION_JSON)), ) }) }