add output formatter

This commit is contained in:
Dietmar Maurer 2018-12-05 12:42:25 +01:00
parent 03862a2eeb
commit 1571873d7b
3 changed files with 69 additions and 9 deletions

View File

@ -23,6 +23,7 @@ pub mod api {
pub mod server { pub mod server {
pub mod formatter;
pub mod rest; pub mod rest;
} }

51
src/server/formatter.rs Normal file
View File

@ -0,0 +1,51 @@
use failure::*;
use serde_json::{json, Value};
pub struct OutputFormatter {
pub format_result: fn(data: &Value) -> (Vec<u8>, &'static str),
}
fn json_format_result(data: &Value) -> (Vec<u8>, &'static str) {
let content_type = "application/json;charset=UTF-8";
let result = json!({
"data": data
});
// todo: set result.total result.changes
let json_str = result.to_string();
let raw = json_str.into_bytes();
(raw, content_type)
}
pub static JSON_FORMATTER: OutputFormatter = OutputFormatter {
format_result: json_format_result,
};
fn extjs_format_result(data: &Value) -> (Vec<u8>, &'static str) {
let content_type = "application/json;charset=UTF-8";
let result = json!({
"data": data,
"success": true
});
// todo: set result.total result.changes
let json_str = result.to_string();
let raw = json_str.into_bytes();
(raw, content_type)
}
pub static EXTJS_FORMATTER: OutputFormatter = OutputFormatter {
format_result: extjs_format_result,
};

View File

@ -1,6 +1,7 @@
use crate::api::schema::*; use crate::api::schema::*;
use crate::api::router::*; use crate::api::router::*;
use crate::api::config::*; use crate::api::config::*;
use super::formatter::*;
use std::fmt; use std::fmt;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
@ -66,7 +67,7 @@ impl Service for ApiService {
match result { match result {
Ok(res) => Ok::<_, hyper::Error>(res), Ok(res) => Ok::<_, hyper::Error>(res),
Err(err) => { Err(err) => {
if let Some(apierr) = err.downcast_ref::<HttpError>() { if let Some(apierr) = err.downcast_ref::<HttpError>() {
let mut resp = Response::new(Body::from(apierr.message.clone())); let mut resp = Response::new(Body::from(apierr.message.clone()));
*resp.status_mut() = apierr.code; *resp.status_mut() = apierr.code;
Ok(resp) Ok(resp)
@ -140,6 +141,7 @@ fn get_request_parameters_async(
if let Some(query_str) = parts.uri.query() { if let Some(query_str) = parts.uri.query() {
for (k, v) in form_urlencoded::parse(query_str.as_bytes()).into_owned() { for (k, v) in form_urlencoded::parse(query_str.as_bytes()).into_owned() {
if k == "_dc" { continue; } // skip extjs "disable cache" parameter
param_list.push((k, v)); param_list.push((k, v));
} }
} }
@ -159,6 +161,7 @@ fn get_request_parameters_async(
fn handle_sync_api_request( fn handle_sync_api_request(
info: &'static ApiMethod, info: &'static ApiMethod,
formatter: &'static OutputFormatter,
parts: Parts, parts: Parts,
req_body: Body, req_body: Body,
uri_param: HashMap<String, String>, uri_param: HashMap<String, String>,
@ -185,15 +188,16 @@ fn handle_sync_api_request(
Ok(res) Ok(res)
}).then(|result| { }).then(move |result| {
match result { match result {
Ok(ref value) => { Ok(ref value) => {
let json_str = value.to_string();
let (raw, content_type) = (formatter.format_result)(value);
Ok(Response::builder() Ok(Response::builder()
.status(StatusCode::OK) .status(StatusCode::OK)
.header(header::CONTENT_TYPE, "application/json") .header(header::CONTENT_TYPE, content_type)
.body(Body::from(json_str))?) .body(Body::from(raw))?)
} }
Err(err) => Err(http_err!(BAD_REQUEST, err.to_string())) Err(err) => Err(http_err!(BAD_REQUEST, err.to_string()))
} }
@ -374,15 +378,19 @@ pub fn handle_request(api: Arc<ApiConfig>, req: Request<Body>) -> BoxFut {
println!("GOT API REQUEST"); println!("GOT API REQUEST");
if comp_len >= 2 { if comp_len >= 2 {
let format = components[1]; let format = components[1];
if format != "json" { let formatter = match format {
return Box::new(future::err(http_err!(BAD_REQUEST, format!("Unsupported output format '{}'.", format)))) "json" => &JSON_FORMATTER,
} "extjs" => &EXTJS_FORMATTER,
_ => {
return Box::new(future::err(http_err!(BAD_REQUEST, format!("Unsupported output format '{}'.", format))));
}
};
let mut uri_param = HashMap::new(); let mut uri_param = HashMap::new();
if let Some(api_method) = api.find_method(&components[2..], method, &mut uri_param) { if let Some(api_method) = api.find_method(&components[2..], method, &mut uri_param) {
// fixme: handle auth // fixme: handle auth
return handle_sync_api_request(api_method, parts, body, uri_param); return handle_sync_api_request(api_method, formatter, parts, body, uri_param);
} }
} }
} else { } else {