2 use lazy_static
::lazy_static
;
4 use std
::collections
::HashMap
;
8 use hyper
::{Body, Request, Response, StatusCode}
;
11 use crate::api_schema
::router
::*;
12 use crate::server
::formatter
::*;
13 use crate::server
::WorkerTask
;
15 use super::environment
::*;
18 static ref BACKUP_ROUTER
: Router
= super::backup_api();
21 pub struct BackupService
{
22 rpcenv
: BackupEnvironment
,
23 worker
: Arc
<WorkerTask
>,
29 pub fn new(rpcenv
: BackupEnvironment
, worker
: Arc
<WorkerTask
>, debug
: bool
) -> Self {
30 Self { rpcenv, worker, debug }
33 pub fn debug
<S
: AsRef
<str>>(&self, msg
: S
) {
34 if self.debug { self.worker.log(msg); }
37 fn handle_request(&self, req
: Request
<Body
>) -> BoxFut
{
39 let (parts
, body
) = req
.into_parts();
41 let method
= parts
.method
.clone();
43 let (path
, components
) = match tools
::normalize_uri_path(parts
.uri
.path()) {
45 Err(err
) => return Box
::new(future
::err(http_err
!(BAD_REQUEST
, err
.to_string()))),
48 self.debug(format
!("{} {}", method
, path
));
50 let mut uri_param
= HashMap
::new();
52 match BACKUP_ROUTER
.find_method(&components
, method
, &mut uri_param
) {
53 MethodDefinition
::None
=> {
54 let err
= http_err
!(NOT_FOUND
, "Path not found.".to_string());
55 return Box
::new(future
::ok((self.rpcenv
.formatter
.format_error
)(err
)));
57 MethodDefinition
::Simple(api_method
) => {
58 return crate::server
::rest
::handle_sync_api_request(
59 self.rpcenv
.clone(), api_method
, self.rpcenv
.formatter
, parts
, body
, uri_param
);
61 MethodDefinition
::Async(async_method
) => {
62 return crate::server
::rest
::handle_async_api_request(
63 self.rpcenv
.clone(), async_method
, self.rpcenv
.formatter
, parts
, body
, uri_param
);
68 fn log_response(worker
: Arc
<WorkerTask
>, method
: hyper
::Method
, path
: &str, resp
: &Response
<Body
>) {
70 let status
= resp
.status();
72 if !status
.is_success() {
73 let reason
= status
.canonical_reason().unwrap_or("unknown reason");
75 let mut message
= "request failed";
76 if let Some(data
) = resp
.extensions().get
::<ErrorMessageExtension
>() {
80 worker
.log(format
!("{} {}: {} {}: {}", method
.as_str(), path
, status
.as_str(), reason
, message
));
85 impl hyper
::service
::Service
for BackupService
{
89 type Future
= Box
<dyn Future
<Item
= Response
<Body
>, Error
= Self::Error
> + Send
>;
91 fn call(&mut self, req
: Request
<Self::ReqBody
>) -> Self::Future
{
92 let path
= req
.uri().path().to_owned();
93 let method
= req
.method().clone();
94 let worker
= self.worker
.clone();
96 Box
::new(self.handle_request(req
).then(move |result
| {
99 Self::log_response(worker
, method
, &path
, &res
);
103 if let Some(apierr
) = err
.downcast_ref
::<HttpError
>() {
104 let mut resp
= Response
::new(Body
::from(apierr
.message
.clone()));
105 resp
.extensions_mut().insert(ErrorMessageExtension(apierr
.message
.clone()));
106 *resp
.status_mut() = apierr
.code
;
107 Self::log_response(worker
, method
, &path
, &resp
);
110 let mut resp
= Response
::new(Body
::from(err
.to_string()));
111 resp
.extensions_mut().insert(ErrorMessageExtension(err
.to_string()));
112 *resp
.status_mut() = StatusCode
::BAD_REQUEST
;
113 Self::log_response(worker
, method
, &path
, &resp
);