]> git.proxmox.com Git - proxmox-backup.git/blame - src/server/formatter.rs
tree-wide: use 'dyn' for all trait objects
[proxmox-backup.git] / src / server / formatter.rs
CommitLineData
1571873d
DM
1use failure::*;
2use serde_json::{json, Value};
3
8225aa2f 4use crate::api_schema::router::{HttpError, RpcEnvironment};
6049b71f 5
c578fcd9
DM
6use hyper::{Body, Response, StatusCode};
7use hyper::header;
8
44c00c0d
DM
9/// Extension to set error message for server side logging
10pub struct ErrorMessageExtension(pub String);
11
1571873d
DM
12pub struct OutputFormatter {
13
dd5495d6 14 pub format_data: fn(data: Value, rpcenv: &dyn RpcEnvironment) -> Response<Body>,
6049b71f
DM
15
16 pub format_error: fn(err: Error) -> Response<Body>,
1571873d
DM
17}
18
0f253593 19static JSON_CONTENT_TYPE: &str = "application/json;charset=UTF-8";
6049b71f 20
78b51915
DM
21pub 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}
6049b71f 27
78b51915 28pub fn json_data_response(data: Value) -> Response<Body> {
6049b71f 29
78b51915 30 let json_str = data.to_string();
6049b71f
DM
31
32 let raw = json_str.into_bytes();
1571873d 33
6049b71f
DM
34 let mut response = Response::new(raw.into());
35 response.headers_mut().insert(
36 header::CONTENT_TYPE,
0f253593 37 header::HeaderValue::from_static(JSON_CONTENT_TYPE));
1571873d 38
6049b71f
DM
39 response
40}
c578fcd9 41
dd5495d6 42fn json_format_data(data: Value, rpcenv: &dyn RpcEnvironment) -> Response<Body> {
c578fcd9 43
6049b71f
DM
44 let mut result = json!({
45 "data": data
46 });
c578fcd9 47
6049b71f
DM
48 if let Some(total) = rpcenv.get_result_attrib("total").and_then(|v| v.as_u64()) {
49 result["total"] = Value::from(total);
50 }
c578fcd9 51
6049b71f
DM
52 if let Some(changes) = rpcenv.get_result_attrib("changes") {
53 result["changes"] = changes.clone();
c578fcd9 54 }
6049b71f 55
78b51915 56 json_data_response(result)
6049b71f
DM
57}
58
78b51915 59pub fn json_error_response(err: Error) -> Response<Body> {
6049b71f 60
8225aa2f
DM
61 let mut response = if let Some(apierr) = err.downcast_ref::<HttpError>() {
62 let mut resp = Response::new(Body::from(apierr.message.clone()));
63 *resp.status_mut() = apierr.code;
64 resp
65 } else {
66 let mut resp = Response::new(Body::from(err.to_string()));
67 *resp.status_mut() = StatusCode::BAD_REQUEST;
68 resp
69 };
70
6049b71f
DM
71 response.headers_mut().insert(
72 header::CONTENT_TYPE,
0f253593 73 header::HeaderValue::from_static(JSON_CONTENT_TYPE));
6049b71f 74
44c00c0d
DM
75 response.extensions_mut().insert(ErrorMessageExtension(err.to_string()));
76
6049b71f 77 response
1571873d
DM
78}
79
80pub static JSON_FORMATTER: OutputFormatter = OutputFormatter {
d55037e4 81 format_data: json_format_data,
78b51915 82 format_error: json_error_response,
1571873d
DM
83};
84
dd5495d6 85fn extjs_format_data(data: Value, rpcenv: &dyn RpcEnvironment) -> Response<Body> {
1571873d 86
6049b71f
DM
87 let mut result = json!({
88 "data": data,
89 "success": true
90 });
1571873d 91
6049b71f
DM
92 if let Some(total) = rpcenv.get_result_attrib("total").and_then(|v| v.as_u64()) {
93 result["total"] = Value::from(total);
94 }
c578fcd9 95
6049b71f
DM
96 if let Some(changes) = rpcenv.get_result_attrib("changes") {
97 result["changes"] = changes.clone();
98 }
c578fcd9 99
c578fcd9 100
78b51915 101 json_data_response(result)
6049b71f 102}
1571873d 103
6049b71f 104fn extjs_format_error(err: Error) -> Response<Body> {
1571873d 105
6049b71f 106 let mut errors = vec![];
5bb33981
DM
107
108 let message = err.to_string();
109 errors.push(&message);
1571873d 110
6049b71f 111 let result = json!({
5bb33981 112 "message": message,
6049b71f
DM
113 "errors": errors,
114 "success": false
115 });
1571873d 116
78b51915 117 let mut response = json_data_response(result);
44c00c0d
DM
118
119 response.extensions_mut().insert(ErrorMessageExtension(message));
120
121 response
1571873d
DM
122}
123
124pub static EXTJS_FORMATTER: OutputFormatter = OutputFormatter {
d55037e4 125 format_data: extjs_format_data,
6049b71f 126 format_error: extjs_format_error,
1571873d 127};