serv/
lib.rs

1extern crate bytes;
2#[macro_use]
3extern crate error_chain;
4extern crate futures;
5extern crate hyper;
6#[macro_use]
7extern crate log;
8extern crate serde;
9#[macro_use]
10extern crate serde_derive;
11#[cfg(feature = "fst")]
12extern crate fst;
13extern crate http;
14extern crate serde_json;
15extern crate serde_qs;
16extern crate tokio;
17extern crate tokio_current_thread;
18extern crate tokio_io;
19#[cfg(feature = "uds")]
20extern crate tokio_uds;
21extern crate url;
22
23pub mod error {
24    use super::*;
25
26    error_chain!{
27        foreign_links {
28            Hyper(hyper::Error);
29            Http(http::Error);
30            Io(std::io::Error);
31        }
32
33        errors {
34            UnexpectedMethod(m: hyper::Method) {
35                description("badarg")
36            }
37            InvalidEndpoint {
38                description("invalid_endpoint")
39            }
40            DecodeJson(e: serde_json::Error) {
41                description("badarg")
42            }
43            EncodeJson(e: serde_json::Error) {
44                description("internal")
45            }
46            DecodeQs(e: serde_qs::Error) {
47                description("badarg")
48            }
49        }
50    }
51}
52
53type SyncObj<T> = std::rc::Rc<T>;
54
55pub mod async;
56pub mod reply;
57pub mod server;
58pub mod sync;
59
60pub use error::{Error, ErrorKind};
61pub use server::Server;
62use std::fmt::Debug;
63
64use futures::future::*;
65use futures::*;
66use hyper::header::*;
67use hyper::service::Service;
68use hyper::{Body, Request, Response};
69
70pub fn resp_err() -> Response<Body> {
71    Response::builder()
72        .status(hyper::StatusCode::BAD_REQUEST)
73        .body(Body::empty())
74        .unwrap_or_else(|_| Response::new(Body::empty()))
75}
76
77pub fn resp_serv_err<E>(e: E, status: hyper::StatusCode) -> Response<Body>
78where
79    E: Debug + std::error::Error,
80{
81    let reply = reply::ServiceReply::<(), E>::from(e);
82    let encoded = match serde_json::to_vec(&reply) {
83        Ok(v) => v,
84        Err(_e) => return resp_err(),
85    };
86
87    Response::builder()
88        .header(ACCESS_CONTROL_ALLOW_ORIGIN, "*")
89        .status(status)
90        .body(Body::from(encoded))
91        .unwrap_or_else(|_| Response::new(Body::empty()))
92}
93
94pub type HyperFuture = Box<Future<Item = Response<Body>, Error = hyper::Error>>;
95pub type HyperService =
96    Box<Service<ReqBody = Body, ResBody = Body, Error = hyper::Error, Future = HyperFuture>>;
97pub type HyperServiceSend = Box<
98    Service<
99        ReqBody = Body,
100        ResBody = Body,
101        Error = hyper::Error,
102        Future = Box<Future<Item = Response<Body>, Error = hyper::Error> + Send>,
103    >,
104>;
105
106/// parse API req from qs/body
107fn parse_req<R>(req: Request<Body>) -> Box<Future<Item = R, Error = Error>>
108where
109    R: for<'de> serde::Deserialize<'de> + 'static,
110{
111    use hyper::Method;
112    match req.method().clone() {
113        Method::GET | Method::DELETE => {
114            let qs = req.uri().query().unwrap_or("");
115            let req: Result<R, Error> =
116                serde_qs::from_str(qs).map_err(|e| ErrorKind::DecodeQs(e).into());
117            Box::new(result(req))
118        }
119        Method::PUT | Method::POST => {
120            let buf = Vec::new();
121
122            let f = req
123                .into_body()
124                .map_err(Error::from)
125                .fold(buf, |mut buf, chunk| {
126                    buf.extend_from_slice(&chunk);
127                    //TODO: move to config?
128                    if buf.len() > 1024 * 1024 * 4 {
129                        Err(Error::from("body too large"))
130                    } else {
131                        Ok(buf)
132                    }
133                })
134                .and_then(move |chunk: Vec<u8>| {
135                    serde_json::from_slice(&chunk).map_err(|e| ErrorKind::DecodeJson(e).into())
136                });
137            Box::new(f)
138        }
139        m => Box::new(err(ErrorKind::UnexpectedMethod(m).into())),
140    }
141}
142
143#[derive(Serialize, Deserialize, Default, Clone, Copy, Debug)]
144pub struct Empty {}