Geoffrey-rs/geoffrey_api/src/commands/mod.rs

72 lines
2.3 KiB
Rust

use crate::commands::add_location::AddLocation;
use crate::commands::find::FindCommand;
use crate::commands::register::Register;
use crate::context::Context;
use crate::Result;
use geoffrey_models::models::response::APIResponse;
use geoffrey_models::models::CommandLevel;
use serde::de::DeserializeOwned;
use serde::Serialize;
use std::fmt::Debug;
use std::sync::Arc;
use warp::filters::BoxedFilter;
use warp::Filter;
pub mod add_location;
pub mod find;
pub mod register;
#[derive(Debug, Clone, PartialEq)]
#[allow(clippy::upper_case_acronyms)]
pub enum RequestType {
POST,
GET,
}
pub trait Command {
type Req: Serialize + DeserializeOwned + Send + 'static + Debug;
type Resp: Serialize + DeserializeOwned + Send;
fn command_name() -> String;
fn request_type() -> RequestType;
fn command_level() -> CommandLevel;
fn run_command(ctx: Arc<Context>, req: Self::Req) -> Result<Self::Resp>;
}
#[allow(clippy::needless_return)]
pub fn create_command_filter<T: Command>(ctx: Arc<Context>) -> BoxedFilter<(impl warp::Reply,)> {
let filter = warp::path(T::command_name())
.and(warp::any().map(move || ctx.clone()))
.and(warp::body::json())
.map(|ctx: Arc<Context>, req: T::Req| {
log::info!("Running command {}", T::command_name());
log::debug!("Request: {:?}", req);
let reply = T::run_command(ctx, req);
if let Ok(reply) = reply {
log::debug!("Successfully processed command");
warp::reply::json(&APIResponse::Response::<T::Resp>(reply))
} else {
let e = reply.err().unwrap();
log::warn!("Got error when processing command: {:?}", e);
warp::reply::json(&APIResponse::<T::Resp>::Error(e))
}
});
if T::request_type() == RequestType::POST {
return filter.and(warp::post()).boxed();
} else {
return filter.and(warp::get()).boxed();
}
}
pub fn command_filter(
ctx: Arc<Context>,
) -> impl Filter<Extract = impl warp::Reply, Error = warp::Rejection> + Clone {
warp::path("command").and(
create_command_filter::<FindCommand>(ctx.clone())
.or(create_command_filter::<AddLocation>(ctx.clone()))
.or(create_command_filter::<Register>(ctx)),
)
}