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.

87 lines
2.7 KiB

pub mod robots;
use serde::Serialize;
use warp::Filter;
use warp::Reply;
use warp::http::StatusCode;
use crate::simple::handling::HandlingError;
use crate::simple::http::APIBuilder;
impl warp::reject::Reject for HandlingError {}
#[derive(Serialize)]
struct APIError {
code: i64,
message: String,
}
fn build_error_response(e: &HandlingError) -> Result<warp::reply::Response, warp::http::Error> {
let (status, code, message) = match e {
HandlingError::DBError(_e) => (
StatusCode::INTERNAL_SERVER_ERROR, 1, format!("Database access error")
),
HandlingError::NotFound => (
StatusCode::NOT_FOUND, 2, format!("Not Found")
),
HandlingError::InternalError => (
StatusCode::INTERNAL_SERVER_ERROR, 3, format!("Internal unexpected error")
),
};
let body = warp::reply::json(&APIError {
code: code,
message: message,
});
Ok(warp::reply::with_status(body, status).into_response())
}
async fn handle_rejection(
r: warp::reject::Rejection,
) -> Result<warp::reply::Response, warp::reject::Rejection> {
eprintln!("{:#?}", r);
r.find::<HandlingError>()
.map(|e| {
build_error_response(e)
.unwrap_or(
StatusCode::INTERNAL_SERVER_ERROR
.into_response()
)
})
.ok_or(r)
}
pub async fn listen(
db_pool: crate::simple::database::PgSharedPool,
addr: impl Into<std::net::SocketAddr> + 'static,
) {
// build a base Filter for our API so that any request of any kind to "/"
// will return "200 OK" with an empty response body
let base = warp::any()
// match a path termination by a "/" character or lack thereof
.and(warp::path::end())
// reply with a "200 OK" with an empty response body
.map(|| warp::reply())
// box the filter so it may be passed be passed around easily
.boxed();
// begin building the API structure from the base Filter
// right now the pool of database connections is the only
// shared resource that we want to passa around when handling requests
let api = APIBuilder::new(base, db_pool)
// mount the "/robots" base prefix for creating
// and listing all robots in the database
.route(robots::all)
// mount the "/robot/{id}" prefix for retrieving and updating robots information
.route(robots::with_id)
// build the final filter that we'll be served
.build()
// attach a recover to handle rejections
.recover(handle_rejection);
// run the server returning a Future that will be run indefinitely
warp::serve(api).run(addr).await
}