hyper_json_server/
server.rs

1use hyper;
2use hyper::header::{ContentLength, ContentType};
3use hyper::server::{Request, Response, Service};
4use hyper::{Method, StatusCode};
5use futures::{future, Future, Stream};
6use futures::future::Either;
7use serde::de::DeserializeOwned;
8use serde::Serialize;
9use serde_json;
10use std::sync::Arc;
11
12error_chain! {
13    errors {
14        NotFound(obj: String) {
15            description("object not found")
16            display("object {} not found", obj)
17        }
18
19        InternalError(s: String) {
20            description("internal server error")
21            display("internal server error {}", s)
22        }
23
24        BadRequest(s: String) {
25            description("bad request")
26            display("bad request {}", s)
27        }
28
29        MethodNotAllowed {
30            description("method not allowed")
31            display("method not allowed")
32        }
33    }
34}
35
36pub struct JsonServer<S> {
37    pub inner: Arc<S>
38}
39
40fn error_to_response(error: Error) -> Response
41{
42    let (status, body) = match error.kind() {
43        &ErrorKind::NotFound(_) => {
44            (StatusCode::NotFound, format!("{}", error))
45        },
46        &ErrorKind::BadRequest(_) => {
47            (StatusCode::BadRequest, format!("{}", error))
48        },
49        &ErrorKind::InternalError(_) => {
50            (StatusCode::InternalServerError, format!("{}", error))
51        },
52        _ => (StatusCode::InternalServerError, format!("{}", error))
53    };
54    let resp = json!({
55        "error": body,
56    });
57    let body = resp.to_string();
58    let body_len = body.len() as u64;
59    Response::new()
60        .with_body(body)
61        .with_header(ContentLength(body_len))
62        .with_header(ContentType::json())
63        .with_status(status)
64}
65
66impl<S: Service + JsonService + 'static> Service for JsonServer<S>
67{
68    type Request = Request;
69    type Response = Response;
70    type Error = hyper::Error;
71    type Future = Box<Future<Item = self::Response, Error = hyper::error::Error>>;
72
73    fn call(&self, req: Request) -> Self::Future {
74        let service = self.inner.clone();
75        Box::new(
76            if *req.method() == Method::Post {
77            match service.deserialize(req.path(), req.method()) {
78            Ok(f) => {
79                let req = req.body().concat2()
80                            .map_err(move |e| ErrorKind::InternalError(e.to_string()).into())
81                            .and_then(move |chunk| f(chunk.as_ref()));
82                let res = req.and_then(move |req| {
83                   service.call(req).then(move |res| {
84                        match service.serialize(res) {
85                            Ok(body) => {
86                                let len = body.len() as u64;
87                                let resp = Response::new()
88                                    .with_body(body)
89                                    .with_header(ContentLength(len))
90                                    .with_header(ContentType::json())
91                                    .with_status(StatusCode::Ok);
92                                future::ok(resp)
93                            },
94                            Err(e) => future::ok(error_to_response(e)),
95                        }
96                   })
97                }).or_else(|e| future::ok(error_to_response(e)));
98                Either::A(res)
99            },
100            Err(e) => {
101                Either::B(future::ok(error_to_response(e)))
102            }
103        } } else {
104                Either::B(future::ok(error_to_response(ErrorKind::MethodNotAllowed.into())))
105            })
106    }
107}
108
109pub trait JsonService where Self: Service {
110    fn deserialize(&self, path: &str, method: &Method) -> Result<fn(&[u8]) -> Result<<Self as Service>::Request>>;
111    fn serialize(&self, resp: ::std::result::Result<Self::Response, <Self as Service>::Error>) -> Result<Vec<u8>>;
112}
113
114impl<S> JsonService for S 
115    where S: Service,
116          <S as Service>::Request: DeserializeOwned + 'static,
117          <S as Service>::Response: Serialize,
118          <S as Service>::Error: Into<Error>,
119{
120    fn deserialize(&self, _path: &str, _method: &Method) -> Result<fn(&[u8]) -> Result<<S as Service>::Request>> {
121        Ok(|body| {
122            match serde_json::from_slice(body) {
123                Ok(vec) => return Ok(vec),
124                Err(e) => return Err(ErrorKind::BadRequest(e.to_string()).into()),
125            }
126        })
127    }
128
129    fn serialize(&self, resp: ::std::result::Result<S::Response, <S as Service>::Error>) -> Result<Vec<u8>> {
130        match resp {
131            Ok(res) => {
132                Ok(serde_json::to_vec(&res).unwrap())
133            }
134            Err(e) => {
135                Err(e.into())
136            }
137        }
138    }
139}