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
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
|
|
}
|