use std::env; use futures::Future; use actix_files as fs; use actix_web::{web, App, HttpServer, HttpResponse, Error}; use lootalot_db::{Pool, DbApi, QueryResult}; type AppPool = web::Data; /// Wraps call to the DbApi and process its result as a async HttpResponse /// /// Provides a convenient way to call the api inside a route definition. Given a connection pool, /// access to the api is granted in a closure. The closure is called in a blocking way and should /// return a QueryResult. /// If the query succeeds, it's result is returned as JSON data. Otherwise, an InternalServerError /// is returned. /// /// # Usage /// ``` /// (...) /// .route("path/to/", /// move |pool: web::Data| { /// // user data can be processed here /// // ... /// db_call(pool, move |api| { /// // ...do what you want with the api /// } /// } /// ) /// ``` pub fn db_call< J: serde::ser::Serialize + Send + 'static, Q: Fn(DbApi) -> QueryResult + Send + 'static, >( pool: AppPool, query: Q, ) -> impl Future { let conn = pool.get().unwrap(); web::block(move || { let api = DbApi::with_conn(&conn); query(api) }) .then(|res| match res { Ok(players) => HttpResponse::Ok().json(players), Err(e) => { dbg!(&e); HttpResponse::InternalServerError().finish() } }) } pub(crate) fn serve() -> std::io::Result<()> { let www_root: String = env::var("WWW_ROOT").expect("WWW_ROOT must be set"); dbg!(&www_root); let pool = lootalot_db::create_pool(); HttpServer::new(move || { App::new() .data(pool.clone()) .route( "/players", web::get().to_async(move |pool: AppPool| { db_call(pool, move |api| api.fetch_players()) }), ) .route( "/update-wealth/{player_id}/{amount}", web::get().to_async(move |pool: AppPool, data: web::Path<(i32, f32)>| { let (player, gold) = *data; db_call(pool, move |api| api.as_player(player).update_wealth(gold)) }), ) .route( "/loot/{player_id}", web::get().to_async(move |pool: AppPool, player_id: web::Path| { let player_id: i32 = *player_id; db_call(pool, move |api| api.as_player(player_id).loot()) }), ) .service(fs::Files::new("/", www_root.clone()).index_file("index.html")) }) .bind("127.0.0.1:8088")? .run() }