]> git.proxmox.com Git - proxmox-backup.git/blob - src/server/formatter.rs
tokio 1.0: delay -> sleep
[proxmox-backup.git] / src / server / formatter.rs
1 use anyhow::{Error};
2 use serde_json::{json, Value};
3
4 use hyper::{Body, Response, StatusCode};
5 use hyper::header;
6
7 use proxmox::api::{HttpError, RpcEnvironment};
8
9 /// Extension to set error message for server side logging
10 pub struct ErrorMessageExtension(pub String);
11
12 pub struct OutputFormatter {
13
14 pub format_data: fn(data: Value, rpcenv: &dyn RpcEnvironment) -> Response<Body>,
15
16 pub format_error: fn(err: Error) -> Response<Body>,
17 }
18
19 static JSON_CONTENT_TYPE: &str = "application/json;charset=UTF-8";
20
21 pub fn json_response(result: Result<Value, Error>) -> Response<Body> {
22 match result {
23 Ok(data) => json_data_response(data),
24 Err(err) => json_error_response(err),
25 }
26 }
27
28 pub fn json_data_response(data: Value) -> Response<Body> {
29
30 let json_str = data.to_string();
31
32 let raw = json_str.into_bytes();
33
34 let mut response = Response::new(raw.into());
35 response.headers_mut().insert(
36 header::CONTENT_TYPE,
37 header::HeaderValue::from_static(JSON_CONTENT_TYPE));
38
39 response
40 }
41
42 fn add_result_attributes(result: &mut Value, rpcenv: &dyn RpcEnvironment)
43 {
44 let attributes = match rpcenv.result_attrib().as_object() {
45 Some(attr) => attr,
46 None => return,
47 };
48
49 for (key, value) in attributes {
50 result[key] = value.clone();
51 }
52 }
53
54 fn json_format_data(data: Value, rpcenv: &dyn RpcEnvironment) -> Response<Body> {
55
56 let mut result = json!({
57 "data": data
58 });
59
60 add_result_attributes(&mut result, rpcenv);
61
62 json_data_response(result)
63 }
64
65 pub fn json_error_response(err: Error) -> Response<Body> {
66
67 let mut response = if let Some(apierr) = err.downcast_ref::<HttpError>() {
68 let mut resp = Response::new(Body::from(apierr.message.clone()));
69 *resp.status_mut() = apierr.code;
70 resp
71 } else {
72 let mut resp = Response::new(Body::from(err.to_string()));
73 *resp.status_mut() = StatusCode::BAD_REQUEST;
74 resp
75 };
76
77 response.headers_mut().insert(
78 header::CONTENT_TYPE,
79 header::HeaderValue::from_static(JSON_CONTENT_TYPE));
80
81 response.extensions_mut().insert(ErrorMessageExtension(err.to_string()));
82
83 response
84 }
85
86 pub static JSON_FORMATTER: OutputFormatter = OutputFormatter {
87 format_data: json_format_data,
88 format_error: json_error_response,
89 };
90
91 fn extjs_format_data(data: Value, rpcenv: &dyn RpcEnvironment) -> Response<Body> {
92
93 let mut result = json!({
94 "data": data,
95 "success": true
96 });
97
98 add_result_attributes(&mut result, rpcenv);
99
100 json_data_response(result)
101 }
102
103 fn extjs_format_error(err: Error) -> Response<Body> {
104
105 let mut errors = vec![];
106
107 let message = err.to_string();
108 errors.push(&message);
109
110 let result = json!({
111 "message": message,
112 "errors": errors,
113 "success": false
114 });
115
116 let mut response = json_data_response(result);
117
118 response.extensions_mut().insert(ErrorMessageExtension(message));
119
120 response
121 }
122
123 pub static EXTJS_FORMATTER: OutputFormatter = OutputFormatter {
124 format_data: extjs_format_data,
125 format_error: extjs_format_error,
126 };