130 lines
3.2 KiB
Rust
130 lines
3.2 KiB
Rust
use failure::*;
|
|
use serde_json::{json, Value};
|
|
|
|
use hyper::{Body, Response, StatusCode};
|
|
use hyper::header;
|
|
|
|
use proxmox::api::{HttpError, RpcEnvironment};
|
|
|
|
/// Extension to set error message for server side logging
|
|
pub struct ErrorMessageExtension(pub String);
|
|
|
|
pub struct OutputFormatter {
|
|
|
|
pub format_data: fn(data: Value, rpcenv: &dyn RpcEnvironment) -> Response<Body>,
|
|
|
|
pub format_error: fn(err: Error) -> Response<Body>,
|
|
}
|
|
|
|
static JSON_CONTENT_TYPE: &str = "application/json;charset=UTF-8";
|
|
|
|
pub fn json_response(result: Result<Value, Error>) -> Response<Body> {
|
|
match result {
|
|
Ok(data) => json_data_response(data),
|
|
Err(err) => json_error_response(err),
|
|
}
|
|
}
|
|
|
|
pub fn json_data_response(data: Value) -> Response<Body> {
|
|
|
|
let json_str = data.to_string();
|
|
|
|
let raw = json_str.into_bytes();
|
|
|
|
let mut response = Response::new(raw.into());
|
|
response.headers_mut().insert(
|
|
header::CONTENT_TYPE,
|
|
header::HeaderValue::from_static(JSON_CONTENT_TYPE));
|
|
|
|
response
|
|
}
|
|
|
|
fn add_result_attributes(result: &mut Value, rpcenv: &dyn RpcEnvironment)
|
|
{
|
|
if let Some(total) = rpcenv.get_result_attrib("total").and_then(|v| v.as_u64()) {
|
|
result["total"] = Value::from(total);
|
|
}
|
|
|
|
if let Some(active) = rpcenv.get_result_attrib("active").and_then(|v| v.as_bool()) {
|
|
result["active"] = Value::from(active);
|
|
}
|
|
|
|
if let Some(changes) = rpcenv.get_result_attrib("changes") {
|
|
result["changes"] = changes.clone();
|
|
}
|
|
}
|
|
|
|
fn json_format_data(data: Value, rpcenv: &dyn RpcEnvironment) -> Response<Body> {
|
|
|
|
let mut result = json!({
|
|
"data": data
|
|
});
|
|
|
|
add_result_attributes(&mut result, rpcenv);
|
|
|
|
json_data_response(result)
|
|
}
|
|
|
|
pub fn json_error_response(err: Error) -> Response<Body> {
|
|
|
|
let mut response = if let Some(apierr) = err.downcast_ref::<HttpError>() {
|
|
let mut resp = Response::new(Body::from(apierr.message.clone()));
|
|
*resp.status_mut() = apierr.code;
|
|
resp
|
|
} else {
|
|
let mut resp = Response::new(Body::from(err.to_string()));
|
|
*resp.status_mut() = StatusCode::BAD_REQUEST;
|
|
resp
|
|
};
|
|
|
|
response.headers_mut().insert(
|
|
header::CONTENT_TYPE,
|
|
header::HeaderValue::from_static(JSON_CONTENT_TYPE));
|
|
|
|
response.extensions_mut().insert(ErrorMessageExtension(err.to_string()));
|
|
|
|
response
|
|
}
|
|
|
|
pub static JSON_FORMATTER: OutputFormatter = OutputFormatter {
|
|
format_data: json_format_data,
|
|
format_error: json_error_response,
|
|
};
|
|
|
|
fn extjs_format_data(data: Value, rpcenv: &dyn RpcEnvironment) -> Response<Body> {
|
|
|
|
let mut result = json!({
|
|
"data": data,
|
|
"success": true
|
|
});
|
|
|
|
add_result_attributes(&mut result, rpcenv);
|
|
|
|
json_data_response(result)
|
|
}
|
|
|
|
fn extjs_format_error(err: Error) -> Response<Body> {
|
|
|
|
let mut errors = vec![];
|
|
|
|
let message = err.to_string();
|
|
errors.push(&message);
|
|
|
|
let result = json!({
|
|
"message": message,
|
|
"errors": errors,
|
|
"success": false
|
|
});
|
|
|
|
let mut response = json_data_response(result);
|
|
|
|
response.extensions_mut().insert(ErrorMessageExtension(message));
|
|
|
|
response
|
|
}
|
|
|
|
pub static EXTJS_FORMATTER: OutputFormatter = OutputFormatter {
|
|
format_data: extjs_format_data,
|
|
format_error: extjs_format_error,
|
|
};
|