hacker-challenge-sgx-general/src/http_server.rs
jakubDoka 09a84a15f3 rewrite (#2)
running clippy fix
separating homepage to a file
adding summary of network security
removing the rewrite structure
removing catch unwind
adding sealing to persistence
redirectng to the upstream
fixing some startup endgecases

Co-authored-by: Jakub Doka <jakub.doka2@gmail.com>
Reviewed-on: SGX/hacker-challenge-sgx#2
2024-11-08 14:33:42 +00:00

89 lines
2.7 KiB
Rust

#![allow(dead_code)]
use crate::{datastore, datastore::Store};
use actix_web::{get, post, web, App, HttpResponse, HttpServer, Responder};
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use std::sync::Arc;
const HOMEPAGE: &str = include_str!("HOMEPAGE.md");
#[get("/")]
async fn homepage(ds: web::Data<Arc<Store>>) -> impl Responder {
let text = HOMEPAGE
.to_string()
.replace("TOKEN_ADDRESS", &ds.get_token_address())
.replace("MINT_AUTHORITY", &ds.get_pubkey_base58());
HttpResponse::Ok().body(text)
}
#[derive(Serialize)]
pub struct NodesResp {
pub ip: String,
pub joined_at: String,
pub last_keepalive: String,
pub mint_requests: u64,
pub mints: u64,
pub ratls_attacks: u64,
pub total_ratls_conns: u64,
pub public: bool,
}
impl From<(String, datastore::NodeInfo)> for NodesResp {
fn from((ip, node_info): (String, datastore::NodeInfo)) -> Self {
let joined_at: DateTime<Utc> = node_info.started_at.into();
let last_keepalive: DateTime<Utc> = node_info.keepalive.into();
let joined_at = joined_at.format("%Y-%m-%d %H:%M:%S").to_string();
let last_keepalive = last_keepalive.format("%Y-%m-%d %H:%M:%S").to_string();
crate::http_server::NodesResp {
ip,
joined_at,
last_keepalive,
mints: node_info.mints,
total_ratls_conns: node_info.ratls_conns,
ratls_attacks: node_info.ratls_attacks,
public: node_info.public,
mint_requests: node_info.mint_requests,
}
}
}
#[get("/nodes")]
async fn get_nodes(ds: web::Data<Arc<Store>>) -> HttpResponse {
HttpResponse::Ok().json(
ds.get_node_list().into_iter().map(Into::<NodesResp>::into).collect::<Vec<NodesResp>>(),
)
}
#[derive(Deserialize)]
struct MintReq {
wallet: String,
}
#[post("/mint")]
async fn mint(ds: web::Data<Arc<Store>>, req: web::Json<MintReq>) -> impl Responder {
ds.increase_mint_requests();
let result =
actix_web::web::block(move || ds.mint(&req.into_inner().wallet).map_err(|e| e.to_string()))
.await
.unwrap(); // TODO: check if this can get a BlockingError
match result {
Ok(s) => HttpResponse::Ok().body(format!(r#"{{ "signature": "{s}"}}"#)),
Err(e) => HttpResponse::InternalServerError().body(format!(r#"{{ "error": "{e}"}}"#)),
}
}
pub async fn init(ds: Arc<Store>) {
HttpServer::new(move || {
App::new()
.app_data(web::Data::new(ds.clone()))
.service(homepage)
.service(get_nodes)
.service(mint)
})
.bind("0.0.0.0:31372")
.unwrap()
.run()
.await
.unwrap();
}