]> git.proxmox.com Git - proxmox-backup.git/blob - src/server/formatter.rs
src/server/rest.rs: improve logs for unauthorized request
[proxmox-backup.git] / src / server / formatter.rs
1 use failure::*;
2 use serde_json::{json, Value};
3
4 use crate::api_schema::router::{HttpError, RpcEnvironment};
5
6 use hyper::{Body, Response, StatusCode};
7 use hyper::header;
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_result: fn(data: Value, rpcenv: &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
22 fn json_response(result: Value) -> Response<Body> {
23
24 let json_str = result.to_string();
25
26 let raw = json_str.into_bytes();
27
28 let mut response = Response::new(raw.into());
29 response.headers_mut().insert(
30 header::CONTENT_TYPE,
31 header::HeaderValue::from_static(JSON_CONTENT_TYPE));
32
33 response
34 }
35
36 fn json_format_result(data: Value, rpcenv: &RpcEnvironment) -> Response<Body> {
37
38 let mut result = json!({
39 "data": data
40 });
41
42 if let Some(total) = rpcenv.get_result_attrib("total").and_then(|v| v.as_u64()) {
43 result["total"] = Value::from(total);
44 }
45
46 if let Some(changes) = rpcenv.get_result_attrib("changes") {
47 result["changes"] = changes.clone();
48 }
49
50 json_response(result)
51 }
52
53 fn json_format_error(err: Error) -> Response<Body> {
54
55 let mut response = if let Some(apierr) = err.downcast_ref::<HttpError>() {
56 let mut resp = Response::new(Body::from(apierr.message.clone()));
57 *resp.status_mut() = apierr.code;
58 resp
59 } else {
60 let mut resp = Response::new(Body::from(err.to_string()));
61 *resp.status_mut() = StatusCode::BAD_REQUEST;
62 resp
63 };
64
65 response.headers_mut().insert(
66 header::CONTENT_TYPE,
67 header::HeaderValue::from_static(JSON_CONTENT_TYPE));
68
69 response.extensions_mut().insert(ErrorMessageExtension(err.to_string()));
70
71 response
72 }
73
74 pub static JSON_FORMATTER: OutputFormatter = OutputFormatter {
75 format_result: json_format_result,
76 format_error: json_format_error,
77 };
78
79 fn extjs_format_result(data: Value, rpcenv: &RpcEnvironment) -> Response<Body> {
80
81 let mut result = json!({
82 "data": data,
83 "success": true
84 });
85
86 if let Some(total) = rpcenv.get_result_attrib("total").and_then(|v| v.as_u64()) {
87 result["total"] = Value::from(total);
88 }
89
90 if let Some(changes) = rpcenv.get_result_attrib("changes") {
91 result["changes"] = changes.clone();
92 }
93
94
95 json_response(result)
96 }
97
98 fn extjs_format_error(err: Error) -> Response<Body> {
99
100 let mut errors = vec![];
101
102 let message = err.to_string();
103 errors.push(&message);
104
105 let result = json!({
106 "message": message,
107 "errors": errors,
108 "success": false
109 });
110
111 let mut response = json_response(result);
112
113 response.extensions_mut().insert(ErrorMessageExtension(message));
114
115 response
116 }
117
118 pub static EXTJS_FORMATTER: OutputFormatter = OutputFormatter {
119 format_result: extjs_format_result,
120 format_error: extjs_format_error,
121 };