peach-workspace/peach-jsonrpc-server/src/lib.rs

141 lines
4.2 KiB
Rust

//! # peach-jsonrpc-server
//!
//! A JSON-RPC server which exposes an API over HTTP.
use std::env;
use std::result::Result;
use jsonrpc_core::{IoHandler, Value};
use jsonrpc_http_server::{AccessControlAllowOrigin, DomainsValidation, ServerBuilder};
use log::info;
use peach_stats::stats;
mod error;
use crate::error::JsonRpcServerError;
/// Create JSON-RPC I/O handler, add RPC methods and launch HTTP server.
pub fn run() -> Result<(), JsonRpcServerError> {
info!("Starting up.");
info!("Creating JSON-RPC I/O handler.");
let mut io = IoHandler::default();
io.add_sync_method("ping", |_| Ok(Value::String("success".to_string())));
// TODO: add blocks of methods according to provided flags
/* PEACH-STATS RPC METHODS */
io.add_sync_method("cpu_stats", move |_| {
info!("Fetching CPU statistics.");
let cpu = stats::cpu_stats().map_err(JsonRpcServerError::Stats)?;
let json_cpu = serde_json::to_string(&cpu).map_err(JsonRpcServerError::Serde)?;
Ok(Value::String(json_cpu))
});
io.add_sync_method("cpu_stats_percent", move |_| {
info!("Fetching CPU statistics as percentages.");
let cpu = stats::cpu_stats_percent().map_err(JsonRpcServerError::Stats)?;
let json_cpu = serde_json::to_string(&cpu).map_err(JsonRpcServerError::Serde)?;
Ok(Value::String(json_cpu))
});
io.add_sync_method("disk_usage", move |_| {
info!("Fetching disk usage statistics.");
let disks = stats::disk_usage().map_err(JsonRpcServerError::Stats)?;
let json_disks = serde_json::to_string(&disks).map_err(JsonRpcServerError::Serde)?;
Ok(Value::String(json_disks))
});
io.add_sync_method("load_average", move |_| {
info!("Fetching system load average statistics.");
let avg = stats::load_average().map_err(JsonRpcServerError::Stats)?;
let json_avg = serde_json::to_string(&avg).map_err(JsonRpcServerError::Serde)?;
Ok(Value::String(json_avg))
});
io.add_sync_method("mem_stats", move |_| {
info!("Fetching current memory statistics.");
let mem = stats::mem_stats().map_err(JsonRpcServerError::Stats)?;
let json_mem = serde_json::to_string(&mem).map_err(JsonRpcServerError::Serde)?;
Ok(Value::String(json_mem))
});
io.add_sync_method("uptime", move |_| {
info!("Fetching system uptime.");
let uptime = stats::uptime().map_err(JsonRpcServerError::Stats)?;
let json_uptime = serde_json::to_string(&uptime).map_err(JsonRpcServerError::Serde)?;
Ok(Value::String(json_uptime))
});
let http_server =
env::var("PEACH_JSONRPC_SERVER").unwrap_or_else(|_| "127.0.0.1:5110".to_string());
info!("Starting JSON-RPC server on {}.", http_server);
let server = ServerBuilder::new(io)
.cors(DomainsValidation::AllowOnly(vec![
AccessControlAllowOrigin::Null,
]))
.start_http(
&http_server
.parse()
.expect("Invalid HTTP address and port combination"),
)
.expect("Unable to start RPC server");
server.wait();
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
use jsonrpc_core::{Error as JsonRpcError, ErrorCode};
use jsonrpc_test as test_rpc;
#[test]
fn rpc_success() {
let rpc = {
let mut io = IoHandler::new();
io.add_sync_method("rpc_success_response", |_| {
Ok(Value::String("success".into()))
});
test_rpc::Rpc::from(io)
};
assert_eq!(rpc.request("rpc_success_response", &()), r#""success""#);
}
#[test]
fn rpc_parse_error() {
let rpc = {
let mut io = IoHandler::new();
io.add_sync_method("rpc_parse_error", |_| {
let e = JsonRpcError {
code: ErrorCode::ParseError,
message: String::from("Parse error"),
data: None,
};
Err(JsonRpcError::from(JsonRpcServerError::MissingParameter(e)))
});
test_rpc::Rpc::from(io)
};
assert_eq!(
rpc.request("rpc_parse_error", &()),
r#"{
"code": -32700,
"message": "Parse error"
}"#
);
}
}