hyper_json_server/
server.rs1use 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}