use dbs_uhttp::{Method, Request, Response};
use crate::http::{ApiError, ApiRequest, ApiResponse, ApiResponsePayload, HttpError};
use crate::http_handler::{
error_response, extract_query_part, parse_body, success_response, translate_status_code,
EndpointHandler, HttpResult,
};
pub const HTTP_ROOT_V1: &str = "/api/v1";
fn convert_to_response<O: FnOnce(ApiError) -> HttpError>(api_resp: ApiResponse, op: O) -> Response {
match api_resp {
Ok(r) => {
use ApiResponsePayload::*;
match r {
Empty => success_response(None),
DaemonInfo(d) => success_response(Some(d)),
FsGlobalMetrics(d) => success_response(Some(d)),
FsFilesMetrics(d) => success_response(Some(d)),
FsFilesPatterns(d) => success_response(Some(d)),
FsBackendInfo(d) => success_response(Some(d)),
FsInflightMetrics(d) => success_response(Some(d)),
_ => panic!("Unexpected response message from API service"),
}
}
Err(e) => {
let status_code = translate_status_code(&e);
error_response(op(e), status_code)
}
}
}
pub struct InfoHandler {}
impl EndpointHandler for InfoHandler {
fn handle_request(
&self,
req: &Request,
kicker: &dyn Fn(ApiRequest) -> ApiResponse,
) -> HttpResult {
match (req.method(), req.body.as_ref()) {
(Method::Get, None) => {
let r = kicker(ApiRequest::GetDaemonInfo);
Ok(convert_to_response(r, HttpError::DaemonInfo))
}
(Method::Put, Some(body)) => {
let conf = parse_body(body)?;
let r = kicker(ApiRequest::ConfigureDaemon(conf));
Ok(convert_to_response(r, HttpError::Configure))
}
_ => Err(HttpError::BadRequest),
}
}
}
pub struct FsBackendInfo {}
impl EndpointHandler for FsBackendInfo {
fn handle_request(
&self,
req: &Request,
kicker: &dyn Fn(ApiRequest) -> ApiResponse,
) -> HttpResult {
match (req.method(), req.body.as_ref()) {
(Method::Get, None) => {
let mountpoint = extract_query_part(req, "mountpoint").ok_or_else(|| {
HttpError::QueryString(
"'mountpoint' should be specified in query string".to_string(),
)
})?;
let r = kicker(ApiRequest::ExportFsBackendInfo(mountpoint));
Ok(convert_to_response(r, HttpError::FsBackendInfo))
}
_ => Err(HttpError::BadRequest),
}
}
}
pub struct MetricsFsGlobalHandler {}
impl EndpointHandler for MetricsFsGlobalHandler {
fn handle_request(
&self,
req: &Request,
kicker: &dyn Fn(ApiRequest) -> ApiResponse,
) -> HttpResult {
match (req.method(), req.body.as_ref()) {
(Method::Get, None) => {
let id = extract_query_part(req, "id");
let r = kicker(ApiRequest::ExportFsGlobalMetrics(id));
Ok(convert_to_response(r, HttpError::GlobalMetrics))
}
_ => Err(HttpError::BadRequest),
}
}
}
pub struct MetricsFsAccessPatternHandler {}
impl EndpointHandler for MetricsFsAccessPatternHandler {
fn handle_request(
&self,
req: &Request,
kicker: &dyn Fn(ApiRequest) -> ApiResponse,
) -> HttpResult {
match (req.method(), req.body.as_ref()) {
(Method::Get, None) => {
let id = extract_query_part(req, "id");
let r = kicker(ApiRequest::ExportFsAccessPatterns(id));
Ok(convert_to_response(r, HttpError::Pattern))
}
_ => Err(HttpError::BadRequest),
}
}
}
pub struct MetricsFsFilesHandler {}
impl EndpointHandler for MetricsFsFilesHandler {
fn handle_request(
&self,
req: &Request,
kicker: &dyn Fn(ApiRequest) -> ApiResponse,
) -> HttpResult {
match (req.method(), req.body.as_ref()) {
(Method::Get, None) => {
let id = extract_query_part(req, "id");
let latest_read_files = extract_query_part(req, "latest")
.map_or(false, |b| b.parse::<bool>().unwrap_or(false));
let r = kicker(ApiRequest::ExportFsFilesMetrics(id, latest_read_files));
Ok(convert_to_response(r, HttpError::FsFilesMetrics))
}
_ => Err(HttpError::BadRequest),
}
}
}
pub struct MetricsFsInflightHandler {}
impl EndpointHandler for MetricsFsInflightHandler {
fn handle_request(
&self,
req: &Request,
kicker: &dyn Fn(ApiRequest) -> ApiResponse,
) -> HttpResult {
match (req.method(), req.body.as_ref()) {
(Method::Get, None) => {
let r = kicker(ApiRequest::ExportFsInflightMetrics);
Ok(convert_to_response(r, HttpError::InflightMetrics))
}
_ => Err(HttpError::BadRequest),
}
}
}