1pub mod analysis;
12pub mod hosting;
13
14pub use analysis::API;
16pub use analysis::CLI;
17pub use analysis::Query;
18pub use hosting::Casino;
19pub use hosting::RoomHandle;
20
21use actix_cors::Cors;
22use actix_web::App;
23use actix_web::HttpResponse;
24use actix_web::HttpServer;
25use actix_web::Responder;
26use actix_web::middleware::Logger;
27use actix_web::web;
28use std::sync::Arc;
29use tokio_postgres::Client;
30
31async fn health(client: web::Data<Arc<Client>>) -> impl Responder {
32 match client
33 .execute("SELECT 1", &[])
34 .await
35 .inspect_err(|e| log::error!("health check failed: {}", e))
36 {
37 Ok(_) => HttpResponse::Ok().body("ok"),
38 Err(_) => HttpResponse::ServiceUnavailable().body("database unavailable"),
39 }
40}
41
42#[rustfmt::skip]
43pub async fn run() -> Result<(), std::io::Error> {
44 let client = rbp_database::db().await;
45 let api = web::Data::new(analysis::API::new(client.clone()));
46 let crypto = web::Data::new(rbp_auth::Crypto::from_env());
47 let casino = web::Data::new(hosting::Casino::new(client.clone()));
48 let client = web::Data::new(client);
49 log::info!("starting unified server");
50 HttpServer::new(move || {
51 App::new()
52 .wrap(Logger::new("%r %s %Ts"))
53 .wrap(
54 Cors::default()
55 .allow_any_origin()
56 .allow_any_method()
57 .allow_any_header(),
58 )
59 .app_data(api.clone())
60 .app_data(casino.clone())
61 .app_data(crypto.clone())
62 .app_data(client.clone())
63 .route("/health", web::get().to(health))
64 .service(
65 web::scope("/auth")
66 .route("/register", web::post().to(rbp_auth::register))
67 .route("/logout", web::post().to(rbp_auth::logout))
68 .route("/login", web::post().to(rbp_auth::login))
69 .route("/me", web::get().to(rbp_auth::me)),
70 )
71 .service(
72 web::scope("/room")
73 .route("/start", web::post().to(hosting::handlers::start))
74 .route("/enter/{room_id}", web::get().to(hosting::handlers::enter))
75 .route("/leave/{room_id}", web::post().to(hosting::handlers::leave)),
76 )
77 .service(
78 web::scope("/api")
79 .route("/replace-obs", web::post().to(analysis::handlers::replace_obs))
80 .route("/nbr-any-abs", web::post().to(analysis::handlers::nbr_any_wrt_abs))
81 .route("/nbr-obs-abs", web::post().to(analysis::handlers::nbr_obs_wrt_abs))
82 .route("/nbr-abs-abs", web::post().to(analysis::handlers::nbr_abs_wrt_abs))
83 .route("/nbr-kfn-abs", web::post().to(analysis::handlers::kfn_wrt_abs))
84 .route("/nbr-knn-abs", web::post().to(analysis::handlers::knn_wrt_abs))
85 .route("/nbr-kgn-abs", web::post().to(analysis::handlers::kgn_wrt_abs))
86 .route("/exp-wrt-str", web::post().to(analysis::handlers::exp_wrt_str))
87 .route("/exp-wrt-abs", web::post().to(analysis::handlers::exp_wrt_abs))
88 .route("/exp-wrt-obs", web::post().to(analysis::handlers::exp_wrt_obs))
89 .route("/hst-wrt-abs", web::post().to(analysis::handlers::hst_wrt_abs))
90 .route("/hst-wrt-obs", web::post().to(analysis::handlers::hst_wrt_obs))
91 .route("/blueprint", web::post().to(analysis::handlers::blueprint)),
92 )
93 })
94 .workers(6)
95 .bind(std::env::var("BIND_ADDR").expect("BIND_ADDR must be set"))?
96 .run()
97 .await
98}