Files
packager/api/src/main.rs

182 lines
4.6 KiB
Rust
Raw Normal View History

2021-09-07 00:02:53 +02:00
use std::convert::Infallible;
2021-09-06 11:40:41 +02:00
2021-09-07 18:48:34 +02:00
use serde::Serialize;
use uuid::Uuid;
2021-09-07 00:02:53 +02:00
use warp::http::StatusCode;
use warp::Filter;
2021-09-06 09:24:04 +02:00
2021-09-07 00:02:53 +02:00
use packager;
2021-09-06 13:28:56 +02:00
2021-09-06 10:00:16 +02:00
#[derive(Debug)]
enum TripItemStatus {
Pending,
Ready,
Packed,
}
#[derive(Debug)]
struct TripItem<'a> {
2021-09-07 00:02:53 +02:00
package_item: &'a packager::PackageItem,
2021-09-06 10:00:16 +02:00
status: TripItemStatus,
}
impl TripItem<'_> {
2021-09-07 00:02:53 +02:00
fn from_package_item(package_item: &packager::PackageItem) -> TripItem {
2021-09-06 10:00:16 +02:00
TripItem {
2021-09-06 11:40:41 +02:00
package_item,
2021-09-06 10:00:16 +02:00
status: TripItemStatus::Pending,
}
}
2021-09-06 11:04:54 +02:00
fn set_status(&mut self, status: TripItemStatus) {
self.status = status;
}
2021-09-06 10:00:16 +02:00
}
#[derive(Debug)]
struct TripList<'a> {
items: Vec<TripItem<'a>>,
}
impl<'a> TripList<'a> {
2021-09-07 00:02:53 +02:00
fn from_package_list(list: &'a packager::PackageList) -> TripList<'a> {
2021-09-06 11:04:54 +02:00
let mut items = Vec::new();
2021-09-06 13:28:56 +02:00
for item in &list.items {
2021-09-06 11:04:54 +02:00
items.push(TripItem::from_package_item(item));
2021-09-06 10:00:16 +02:00
}
2021-09-06 11:40:41 +02:00
TripList { items }
2021-09-06 10:00:16 +02:00
}
}
#[derive(Debug)]
struct Trip<'a> {
2021-09-06 09:24:04 +02:00
name: String,
2021-09-06 10:00:16 +02:00
date: String,
list: TripList<'a>,
}
impl<'a> Trip<'a> {
2021-09-07 00:02:53 +02:00
fn from_package_list(name: String, date: String, list: &'a packager::PackageList) -> Trip<'a> {
2021-09-06 10:00:16 +02:00
Trip {
2021-09-06 11:40:41 +02:00
name,
date,
2021-09-06 10:00:16 +02:00
list: TripList::from_package_list(list),
}
}
2021-09-06 09:24:04 +02:00
}
2021-09-07 18:48:34 +02:00
// for list in &lists {
// println!("Contents of package list {:?}:", list.name);
// for item in &list.items {
// println!("\t{:?}", item);
// }
// }
// println!("\nNow we're starting an actual trip!");
// let mut trip = Trip::from_package_list(
// String::from("Campingtrip"),
// String::from("2021-09-06"),
// &lists[0],
// );
// println!(
// "\nPackage list for trip {:?} at {:?}:",
// trip.name, trip.date
// );
// for item in &trip.list.items {
// println!("{:?}", item);
// }
// trip.list.items[0].set_status(TripItemStatus::Ready);
// trip.list.items[1].set_status(TripItemStatus::Packed);
// for item in &trip.list.items {
// println!("{:?}", item);
// }
2021-09-07 00:02:53 +02:00
#[derive(Serialize)]
struct ErrorMessage {
code: u16,
success: bool,
message: String,
}
#[derive(Debug)]
struct InvalidUuid;
impl warp::reject::Reject for InvalidUuid {}
// See https://github.com/seanmonstar/warp/blob/master/examples/rejections.rs
async fn handle_rejection(err: warp::Rejection) -> Result<impl warp::Reply, Infallible> {
let code;
let message;
if err.is_not_found() {
message = "NOT_FOUND";
code = StatusCode::NOT_FOUND;
} else if let Some(InvalidUuid) = err.find() {
code = StatusCode::BAD_REQUEST;
message = "INVALID_UUID";
} else if let Some(e) = err.find::<warp::filters::body::BodyDeserializeError>() {
message = "BAD_REQUEST";
code = StatusCode::BAD_REQUEST;
} else if let Some(_) = err.find::<warp::reject::MethodNotAllowed>() {
message = "METHOD_NOT_ALLOWED";
code = StatusCode::METHOD_NOT_ALLOWED;
} else {
// We should have expected this... Just log and say its a 500
eprintln!("unhandled rejection: {:?}", err);
message = "UNHANDLED_REJECTION";
code = StatusCode::INTERNAL_SERVER_ERROR;
}
let json = warp::reply::json(&ErrorMessage {
success: false,
code: code.as_u16(),
message: message.into(),
});
Ok(warp::reply::with_status(json, code))
2021-09-06 13:28:56 +02:00
}
#[tokio::main]
async fn main() {
let accept_json = warp::header::exact("accept", "application/json");
2021-09-06 15:46:02 +02:00
let cors = warp::cors().allow_any_origin();
2021-09-06 13:28:56 +02:00
let root = warp::path::end().map(|| "Hi");
let v1 = warp::path!("v1")
.and(warp::get())
.and(warp::path::end())
.map(warp::reply);
let lists = warp::path!("v1" / "lists")
.and(warp::path::end())
.and(warp::get())
.and(accept_json)
2021-09-07 00:02:53 +02:00
.map(|| warp::reply::json(&packager::get_lists()))
.with(&cors);
let list = warp::path!("v1" / "lists" / String)
.and(warp::path::end())
.and(warp::get())
.and(accept_json)
.and_then(|id: String| async move {
match Uuid::parse_str(&id) {
Ok(uuid) => {
let list = &packager::get_list(uuid);
match list {
Some(l) => Ok(warp::reply::json(l)),
None => Err(warp::reject::not_found()),
}
}
Err(e) => Err(warp::reject::custom(InvalidUuid)),
}
})
.with(&cors)
.recover(handle_rejection);
let routes = root.or(v1).or(lists).or(list);
2021-09-06 13:28:56 +02:00
warp::serve(routes).run(([127, 0, 0, 1], 9000)).await;
2021-09-06 09:24:04 +02:00
}