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 { 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 { eprintln!("{:#?}", r); r.find::() .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 + '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 }