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,
};
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),
Events(d) => success_response(Some(d)),
BackendMetrics(d) => success_response(Some(d)),
BlobcacheMetrics(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 StartHandler {}
impl EndpointHandler for StartHandler {
fn handle_request(
&self,
req: &Request,
kicker: &dyn Fn(ApiRequest) -> ApiResponse,
) -> HttpResult {
match (req.method(), req.body.as_ref()) {
(Method::Put, None) => {
let r = kicker(ApiRequest::Start);
Ok(convert_to_response(r, HttpError::Configure))
}
_ => Err(HttpError::BadRequest),
}
}
}
pub struct ExitHandler {}
impl EndpointHandler for ExitHandler {
fn handle_request(
&self,
req: &Request,
kicker: &dyn Fn(ApiRequest) -> ApiResponse,
) -> HttpResult {
match (req.method(), req.body.as_ref()) {
(Method::Put, None) => {
let r = kicker(ApiRequest::Exit);
Ok(convert_to_response(r, HttpError::Configure))
}
_ => Err(HttpError::BadRequest),
}
}
}
pub struct EventsHandler {}
impl EndpointHandler for EventsHandler {
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::GetEvents);
Ok(convert_to_response(r, HttpError::Events))
}
_ => Err(HttpError::BadRequest),
}
}
}
pub struct MetricsBackendHandler {}
impl EndpointHandler for MetricsBackendHandler {
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::ExportBackendMetrics(id));
Ok(convert_to_response(r, HttpError::BackendMetrics))
}
_ => Err(HttpError::BadRequest),
}
}
}
pub struct MetricsBlobcacheHandler {}
impl EndpointHandler for MetricsBlobcacheHandler {
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::ExportBlobcacheMetrics(id));
Ok(convert_to_response(r, HttpError::BlobcacheMetrics))
}
_ => Err(HttpError::BadRequest),
}
}
}
pub struct MountHandler {}
impl EndpointHandler for MountHandler {
fn handle_request(
&self,
req: &Request,
kicker: &dyn Fn(ApiRequest) -> ApiResponse,
) -> HttpResult {
let mountpoint = extract_query_part(req, "mountpoint").ok_or_else(|| {
HttpError::QueryString("'mountpoint' should be specified in query string".to_string())
})?;
match (req.method(), req.body.as_ref()) {
(Method::Post, Some(body)) => {
let cmd = parse_body(body)?;
let r = kicker(ApiRequest::Mount(mountpoint, cmd));
Ok(convert_to_response(r, HttpError::Mount))
}
(Method::Put, Some(body)) => {
let cmd = parse_body(body)?;
let r = kicker(ApiRequest::Remount(mountpoint, cmd));
Ok(convert_to_response(r, HttpError::Mount))
}
(Method::Delete, None) => {
let r = kicker(ApiRequest::Umount(mountpoint));
Ok(convert_to_response(r, HttpError::Mount))
}
_ => Err(HttpError::BadRequest),
}
}
}
pub struct SendFuseFdHandler {}
impl EndpointHandler for SendFuseFdHandler {
fn handle_request(
&self,
req: &Request,
kicker: &dyn Fn(ApiRequest) -> ApiResponse,
) -> HttpResult {
match (req.method(), req.body.as_ref()) {
(Method::Put, None) => {
let r = kicker(ApiRequest::SendFuseFd);
Ok(convert_to_response(r, HttpError::Upgrade))
}
_ => Err(HttpError::BadRequest),
}
}
}
pub struct TakeoverFuseFdHandler {}
impl EndpointHandler for TakeoverFuseFdHandler {
fn handle_request(
&self,
req: &Request,
kicker: &dyn Fn(ApiRequest) -> ApiResponse,
) -> HttpResult {
match (req.method(), req.body.as_ref()) {
(Method::Put, None) => {
let r = kicker(ApiRequest::TakeoverFuseFd);
Ok(convert_to_response(r, HttpError::Upgrade))
}
_ => Err(HttpError::BadRequest),
}
}
}