From 32f3db27bd2f5dbad02fba8a2b9f6c643769be18 Mon Sep 17 00:00:00 2001 From: Dietmar Maurer Date: Sat, 26 Jan 2019 14:50:37 +0100 Subject: [PATCH] api: pass RpcEnvirnment to api handlers --- src/server/formatter.rs | 118 ++++++++++++++++++++++------------------ src/server/rest.rs | 35 ++++++++++-- 2 files changed, 93 insertions(+), 60 deletions(-) diff --git a/src/server/formatter.rs b/src/server/formatter.rs index decd7063..526c8e07 100644 --- a/src/server/formatter.rs +++ b/src/server/formatter.rs @@ -1,91 +1,101 @@ use failure::*; use serde_json::{json, Value}; +use crate::api::router::RpcEnvironment; + use hyper::{Body, Response, StatusCode}; use hyper::header; pub struct OutputFormatter { - pub format_result: fn(data: Result) -> Response, + pub format_result: fn(data: Value, rpcenv: &RpcEnvironment) -> Response, + + pub format_error: fn(err: Error) -> Response, } -fn json_format_result(data: Result) -> Response { +static json_content_type: &str = "application/json;charset=UTF-8"; + + +fn json_response(result: Value) -> Response { + + let json_str = result.to_string(); + + let raw = json_str.into_bytes(); - let content_type = "application/json;charset=UTF-8"; + let mut response = Response::new(raw.into()); + response.headers_mut().insert( + header::CONTENT_TYPE, + header::HeaderValue::from_static(json_content_type)); - match data { - Ok(value) => { - let result = json!({ - "data": value - }); + response +} - // todo: set result.total result.changes +fn json_format_result(data: Value, rpcenv: &RpcEnvironment) -> Response { - let json_str = result.to_string(); + let mut result = json!({ + "data": data + }); - let raw = json_str.into_bytes(); + if let Some(total) = rpcenv.get_result_attrib("total").and_then(|v| v.as_u64()) { + result["total"] = Value::from(total); + } - let mut response = Response::new(raw.into()); - response.headers_mut().insert( - header::CONTENT_TYPE, - header::HeaderValue::from_static(content_type)); - return response; - } - Err(err) => { - let mut response = Response::new(Body::from(err.to_string())); - response.headers_mut().insert( - header::CONTENT_TYPE, - header::HeaderValue::from_static(content_type)); - *response.status_mut() = StatusCode::BAD_REQUEST; - return response; - } + if let Some(changes) = rpcenv.get_result_attrib("changes") { + result["changes"] = changes.clone(); } + + json_response(result) +} + +fn json_format_error(err: Error) -> Response { + + let mut response = Response::new(Body::from(err.to_string())); + response.headers_mut().insert( + header::CONTENT_TYPE, + header::HeaderValue::from_static(json_content_type)); + *response.status_mut() = StatusCode::BAD_REQUEST; + + response } pub static JSON_FORMATTER: OutputFormatter = OutputFormatter { format_result: json_format_result, + format_error: json_format_error, }; -fn extjs_format_result(data: Result) -> Response { +fn extjs_format_result(data: Value, rpcenv: &RpcEnvironment) -> Response { - let content_type = "application/json;charset=UTF-8"; + let mut result = json!({ + "data": data, + "success": true + }); - let result = match data { - Ok(value) => { - let result = json!({ - "data": value, - "success": true - }); - - // todo: set result.total result.changes + if let Some(total) = rpcenv.get_result_attrib("total").and_then(|v| v.as_u64()) { + result["total"] = Value::from(total); + } - result - } - Err(err) => { - let mut errors = vec![]; + if let Some(changes) = rpcenv.get_result_attrib("changes") { + result["changes"] = changes.clone(); + } - errors.push(err.to_string()); - let result = json!({ - "errors": errors, - "success": false - }); + json_response(result) +} - result - } - }; +fn extjs_format_error(err: Error) -> Response { - let json_str = result.to_string(); + let mut errors = vec![]; + errors.push(err.to_string()); - let raw = json_str.into_bytes(); + let result = json!({ + "errors": errors, + "success": false + }); - let mut response = Response::new(raw.into()); - response.headers_mut().insert( - header::CONTENT_TYPE, - header::HeaderValue::from_static(content_type)); - response + json_response(result) } pub static EXTJS_FORMATTER: OutputFormatter = OutputFormatter { format_result: extjs_format_result, + format_error: extjs_format_error, }; diff --git a/src/server/rest.rs b/src/server/rest.rs index 97e80e10..3812ffb6 100644 --- a/src/server/rest.rs +++ b/src/server/rest.rs @@ -26,6 +26,27 @@ use hyper::service::{Service, NewService}; use hyper::rt::{Future, Stream}; use hyper::header; +struct RestEnvironment { + result_attributes: HashMap, +} + +impl RestEnvironment { + fn new() -> Self { + Self { result_attributes: HashMap::new() } + } +} + +impl RpcEnvironment for RestEnvironment { + + fn set_result_attrib(&mut self, name: &str, value: Value) { + self.result_attributes.insert(name.into(), value); + } + + fn get_result_attrib(&self, name: &str) -> Option<&Value> { + self.result_attributes.get(name) + } +} + pub struct RestServer { pub api_config: Arc, } @@ -169,10 +190,12 @@ fn handle_sync_api_request( let resp = params .and_then(move |params| { - let res = (info.handler)(params, info)?; - Ok(res) - }).then(move |result| { - Ok((formatter.format_result)(result)) + let mut rpcenv = RestEnvironment::new(); + let resp = match (info.handler)(params, info, &mut rpcenv) { + Ok(data) => (formatter.format_result)(data, &rpcenv), + Err(err) => (formatter.format_error)(err), + }; + Ok(resp) }); Box::new(resp) @@ -203,7 +226,7 @@ fn handle_async_api_request( let params = match parse_parameter_strings(¶m_list, &info.parameters, true) { Ok(v) => v, Err(err) => { - let resp = (formatter.format_result)(Err(Error::from(err))); + let resp = (formatter.format_error)(Error::from(err)); return Box::new(future::ok(resp)); } }; @@ -211,7 +234,7 @@ fn handle_async_api_request( match (info.handler)(parts, req_body, params, info) { Ok(future) => future, Err(err) => { - let resp = (formatter.format_result)(Err(Error::from(err))); + let resp = (formatter.format_error)(Error::from(err)); Box::new(future::ok(resp)) } } -- 2.39.5