]>
Commit | Line | Data |
---|---|---|
bd1507c4 DM |
1 | use failure::*; |
2 | use lazy_static::lazy_static; | |
3 | ||
4 | use std::collections::HashMap; | |
5 | use std::sync::Arc; | |
6 | ||
7 | use futures::*; | |
8 | use hyper::{Body, Request, Response, StatusCode}; | |
9 | ||
10 | use crate::tools; | |
11 | use crate::api_schema::router::*; | |
12 | use crate::server::formatter::*; | |
13 | use crate::server::WorkerTask; | |
14 | ||
15 | use super::environment::*; | |
16 | ||
17 | lazy_static!{ | |
18 | static ref BACKUP_ROUTER: Router = super::backup_api(); | |
19 | } | |
20 | ||
21 | ||
22 | pub struct BackupService { | |
23 | rpcenv: BackupEnvironment, | |
24 | worker: Arc<WorkerTask>, | |
25 | } | |
26 | ||
27 | impl BackupService { | |
28 | ||
29 | pub fn new(rpcenv: BackupEnvironment, worker: Arc<WorkerTask>) -> Self { | |
30 | Self { rpcenv, worker } | |
31 | } | |
32 | ||
33 | fn handle_request(&self, req: Request<Body>) -> BoxFut { | |
34 | ||
35 | let (parts, body) = req.into_parts(); | |
36 | ||
37 | let method = parts.method.clone(); | |
38 | ||
39 | let (path, components) = match tools::normalize_uri_path(parts.uri.path()) { | |
40 | Ok((p,c)) => (p, c), | |
41 | Err(err) => return Box::new(future::err(http_err!(BAD_REQUEST, err.to_string()))), | |
42 | }; | |
43 | ||
bd1507c4 DM |
44 | self.worker.log(format!("H2 REQUEST {} {}", method, path)); |
45 | self.worker.log(format!("H2 COMPO {:?}", components)); | |
46 | ||
47 | let mut uri_param = HashMap::new(); | |
48 | ||
49 | match BACKUP_ROUTER.find_method(&components, method, &mut uri_param) { | |
50 | MethodDefinition::None => { | |
51 | let err = http_err!(NOT_FOUND, "Path not found.".to_string()); | |
b4b63e52 | 52 | return Box::new(future::ok((self.rpcenv.formatter.format_error)(err))); |
bd1507c4 DM |
53 | } |
54 | MethodDefinition::Simple(api_method) => { | |
b4b63e52 DM |
55 | return crate::server::rest::handle_sync_api_request( |
56 | self.rpcenv.clone(), api_method, self.rpcenv.formatter, parts, body, uri_param); | |
bd1507c4 DM |
57 | } |
58 | MethodDefinition::Async(async_method) => { | |
b4b63e52 DM |
59 | return crate::server::rest::handle_async_api_request( |
60 | self.rpcenv.clone(), async_method, self.rpcenv.formatter, parts, body, uri_param); | |
bd1507c4 DM |
61 | } |
62 | } | |
63 | } | |
64 | ||
65 | fn log_response(worker: Arc<WorkerTask>, method: hyper::Method, path: &str, resp: &Response<Body>) { | |
66 | ||
67 | let status = resp.status(); | |
68 | ||
69 | if !status.is_success() { | |
70 | let reason = status.canonical_reason().unwrap_or("unknown reason"); | |
71 | ||
72 | let mut message = "request failed"; | |
73 | if let Some(data) = resp.extensions().get::<ErrorMessageExtension>() { | |
74 | message = &data.0; | |
75 | } | |
76 | ||
77 | worker.log(format!("{} {}: {} {}: {}", method.as_str(), path, status.as_str(), reason, message)); | |
78 | } | |
79 | } | |
80 | } | |
81 | ||
82 | impl hyper::service::Service for BackupService { | |
83 | type ReqBody = Body; | |
84 | type ResBody = Body; | |
85 | type Error = hyper::Error; | |
86 | type Future = Box<Future<Item = Response<Body>, Error = Self::Error> + Send>; | |
87 | ||
88 | fn call(&mut self, req: Request<Self::ReqBody>) -> Self::Future { | |
89 | let path = req.uri().path().to_owned(); | |
90 | let method = req.method().clone(); | |
91 | let worker = self.worker.clone(); | |
92 | ||
93 | Box::new(self.handle_request(req).then(move |result| { | |
94 | match result { | |
95 | Ok(res) => { | |
96 | Self::log_response(worker, method, &path, &res); | |
97 | Ok::<_, hyper::Error>(res) | |
98 | } | |
99 | Err(err) => { | |
100 | if let Some(apierr) = err.downcast_ref::<HttpError>() { | |
101 | let mut resp = Response::new(Body::from(apierr.message.clone())); | |
907f5bb0 | 102 | resp.extensions_mut().insert(ErrorMessageExtension(apierr.message.clone())); |
bd1507c4 DM |
103 | *resp.status_mut() = apierr.code; |
104 | Self::log_response(worker, method, &path, &resp); | |
105 | Ok(resp) | |
106 | } else { | |
107 | let mut resp = Response::new(Body::from(err.to_string())); | |
907f5bb0 | 108 | resp.extensions_mut().insert(ErrorMessageExtension(err.to_string())); |
bd1507c4 DM |
109 | *resp.status_mut() = StatusCode::BAD_REQUEST; |
110 | Self::log_response(worker, method, &path, &resp); | |
111 | Ok(resp) | |
112 | } | |
113 | } | |
114 | } | |
115 | })) | |
116 | } | |
117 | } |