You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

157 lines
4.5 KiB

use crate::simple::database::PgSharedPool;
use crate::simple::http::reply_json;
use warp::{Filter, Rejection, Reply};
use warp::filters::{body, method, query as params};
use warp::http::StatusCode;
use serde::{Deserialize, Serialize};
use crate::app;
#[derive(Deserialize)]
struct PaginationOptions {
pub offset: i64,
pub limit: i64,
}
#[derive(Serialize)]
struct Pagination<T> {
pub data: Vec<T>,
pub next: bool,
}
// add a new robot entry
async fn create(
shared: std::sync::Arc<std::boxed::Box<crate::simple::shared::SharedContainer>>,
r: app::forms::GetRobot,
) -> Result<impl Reply, Rejection> {
reply_json(app::robots::add_robot(shared, r).await)
}
// retrieve information of a single robot
async fn get(
shared: std::sync::Arc<std::boxed::Box<crate::simple::shared::SharedContainer>>,
id: i64,
) -> Result<impl Reply, Rejection> {
reply_json(app::robots::get_robot(shared, id).await)
}
// updates robot information
async fn update(
pool: std::sync::Arc<std::boxed::Box<crate::simple::shared::SharedContainer>>,
id: i64,
r: app::forms::GetRobot,
) -> Result<impl Reply, Rejection> {
reply_json(app::robots::update_robot(pool, id, r).await)
}
// returns a pagination of all robots
async fn get_all(
pool: std::sync::Arc<std::boxed::Box<crate::simple::shared::SharedContainer>>,
p: PaginationOptions,
) -> Result<impl Reply, Rejection> {
reply_json(
app::robots::get_all(pool, p.offset, p.limit)
.await
.map(|(r, next)| Pagination {
data: r,
next: next,
}),
)
}
// will delete the requested robot
async fn delete(
pool: std::sync::Arc<std::boxed::Box<crate::simple::shared::SharedContainer>>,
id: i64,
) -> Result<impl Reply, Rejection> {
match app::robots::delete_robot(pool, id).await {
Ok(_) => Ok(warp::reply::with_status(
warp::reply(),
StatusCode::NO_CONTENT,
)),
Err(e) => Err(warp::reject::custom(e)),
}
}
// builds the route structure for "/robots" endpoint
pub fn all(
base: warp::filters::BoxedFilter<(impl Reply + 'static,)>,
pool: std::sync::Arc<std::boxed::Box<crate::simple::shared::SharedContainer>>,
) -> warp::filters::BoxedFilter<(impl Reply,)> {
// create a prefix that injects a database connection for every request
// every filter is added after the prefix so it receives a database connection
let prefix = warp::path!("robots").map(move || pool.clone());
base.or(
// filter for creating new robots
prefix
.clone()
// match HTTP POST method
.and(method::post())
// attempts to parse the request's body as JSON
.and(body::json())
// bind the handler
.and_then(create),
)
.or(
// filter for retrieving a pagination of robots
prefix
.clone()
// match HTTP GET method
.and(method::get())
// add pagination query parameters
.and(params::query())
// bind the handler
.and_then(get_all),
)
.boxed()
}
// builds the route structure for the "/robot/{id}" endpoint
pub fn with_id(
base: warp::filters::BoxedFilter<(impl Reply + 'static,)>,
pool: std::sync::Arc<std::boxed::Box<crate::simple::shared::SharedContainer>>,
) -> warp::filters::BoxedFilter<(impl Reply,)> {
// we create a prefix containing the id of a robot and a shared database connection
// every filter is added after the prefix
// so it receives a robot's id and a database connection
let prefix = warp::path!("robot" / i64)
.map(move |id| (pool.clone(), id))
.untuple_one();
// append the routes to the base filter
base.or(
// filter to get information on a robot
prefix
.clone()
// match HTTP GET method
.and(method::get())
// bind the handler
.and_then(get),
)
.or(
// filter for updating individual robots
prefix
.clone()
// match HTTP POST method
.and(method::put())
// attempts to parse the request's body as JSON
.and(body::json())
// bind the handler
.and_then(update),
)
.or(
// filter that deletes a robot entry
prefix
.clone()
// match HTTP DELETE method
.and(method::delete())
// bind the handler
.and_then(delete),
)
.boxed()
}