server: server struct

This commit is contained in:
nym21
2025-03-06 14:52:26 +01:00
parent d2ca6f1d46
commit f1851b304c
10 changed files with 125 additions and 112 deletions
+3 -3
View File
@@ -3,9 +3,9 @@ use axum::{Router, routing::get};
use super::AppState;
mod explorer;
mod vecs;
mod query;
pub use vecs::DTS;
pub use query::DTS;
pub trait ApiRoutes {
fn add_api_routes(self) -> Self;
@@ -13,6 +13,6 @@ pub trait ApiRoutes {
impl ApiRoutes for Router<AppState> {
fn add_api_routes(self) -> Self {
self.route("/api/vecs", get(vecs::handler))
self.route("/api/query", get(query::handler))
}
}
@@ -7,8 +7,6 @@ use axum::{
response::{IntoResponse, Response},
};
use brk_query::{Format, Index, Output, Params};
use color_eyre::eyre::eyre;
use serde_json::Value;
use crate::{log_result, traits::HeaderMapExtended};
@@ -26,17 +24,15 @@ pub async fn handler(
) -> Response {
let instant = Instant::now();
let path = uri.path();
match req_to_response_res(headers, query, app_state) {
Ok(response) => {
log_result(response.status(), path, instant);
log_result(response.status(), &uri, instant);
response
}
Err(error) => {
let mut response =
(StatusCode::INTERNAL_SERVER_ERROR, error.to_string()).into_response();
log_result(response.status(), path, instant);
log_result(response.status(), &uri, instant);
response.headers_mut().insert_cors();
response
}
+11 -9
View File
@@ -7,7 +7,7 @@ use std::{
use axum::{
body::Body,
extract::{self, State},
http::{HeaderMap, StatusCode},
http::{HeaderMap, StatusCode, Uri},
response::{IntoResponse, Response},
};
use log::{error, info};
@@ -22,18 +22,24 @@ use super::minify::minify_js;
pub async fn file_handler(
headers: HeaderMap,
State(app_state): State<AppState>,
uri: Uri,
path: extract::Path<String>,
) -> Response {
any_handler(headers, app_state, Some(path))
any_handler(headers, app_state, uri, Some(path))
}
pub async fn index_handler(headers: HeaderMap, State(app_state): State<AppState>) -> Response {
any_handler(headers, app_state, None)
pub async fn index_handler(
headers: HeaderMap,
State(app_state): State<AppState>,
uri: Uri,
) -> Response {
any_handler(headers, app_state, uri, None)
}
fn any_handler(
headers: HeaderMap,
app_state: AppState,
uri: Uri,
path: Option<extract::Path<String>>,
) -> Response {
let website_path = app_state
@@ -70,11 +76,7 @@ fn any_handler(
path_to_response(&headers, &website_path.join("index.html"))
};
log_result(
response.status(),
&format!("/{}", path.map_or("".to_owned(), |p| p.0)),
instant,
);
log_result(response.status(), &uri, instant);
response
}
+93 -79
View File
@@ -11,7 +11,12 @@ use std::{
};
use api::{ApiRoutes, DTS};
use axum::{Json, Router, http::StatusCode, routing::get, serve};
use axum::{
Json, Router,
http::{StatusCode, Uri},
routing::get,
serve,
};
use brk_computer::Computer;
use brk_core::path_dot_brk;
use brk_indexer::Indexer;
@@ -31,6 +36,8 @@ pub use files::Frontend;
#[derive(Clone)]
pub struct AppState {
// indexer: &'static Indexer,
// computer: &'static Computer,
query: &'static Query<'static>,
frontend: Frontend,
websites_path: Option<PathBuf>,
@@ -41,99 +48,106 @@ const DOWNLOADS: &str = "downloads";
const WEBSITES: &str = "websites";
// TODO
pub struct Server;
pub struct Server(AppState);
pub async fn main(
indexer: Indexer,
computer: Computer,
frontend: Frontend,
) -> color_eyre::Result<()> {
let indexer = Box::leak(Box::new(indexer));
let computer = Box::leak(Box::new(computer));
let query = Box::leak(Box::new(Query::build(indexer, computer)));
impl Server {
pub fn new(
indexer: Indexer,
computer: Computer,
frontend: Frontend,
) -> color_eyre::Result<Self> {
let indexer = Box::leak(Box::new(indexer));
let computer = Box::leak(Box::new(computer));
let query = Box::leak(Box::new(Query::build(indexer, computer)));
let websites_path = if frontend.is_some() {
let websites_dev_path = Path::new(DEV_PATH).join(WEBSITES);
let websites_path = if frontend.is_some() {
let websites_dev_path = Path::new(DEV_PATH).join(WEBSITES);
let websites_path = if fs::exists(&websites_dev_path)? {
websites_dev_path
let websites_path = if fs::exists(&websites_dev_path)? {
websites_dev_path
} else {
let downloads_path = path_dot_brk().join(DOWNLOADS);
let downloaded_websites_path = downloads_path.join("brk-main").join(WEBSITES);
if !fs::exists(&downloaded_websites_path)? {
info!("Downloading websites from Github...");
// TODO
// Need to download versioned, this is only for testing !
let url =
"https://github.com/bitcoinresearchkit/brk/archive/refs/heads/main.zip";
let response = minreq::get(url).send()?;
let bytes = response.as_bytes();
let cursor = Cursor::new(bytes);
let mut zip = zip::ZipArchive::new(cursor)?;
zip.extract(&downloads_path)?;
}
downloaded_websites_path
};
query.generate_dts_file(frontend, websites_path.as_path())?;
Some(websites_path)
} else {
let downloads_path = path_dot_brk().join(DOWNLOADS);
let downloaded_websites_path = downloads_path.join("brk-main").join(WEBSITES);
if !fs::exists(&downloaded_websites_path)? {
info!("Downloading websites from Github...");
// TODO
// Need to download versioned, this is only for testing !
let url = "https://github.com/bitcoinresearchkit/brk/archive/refs/heads/main.zip";
let response = minreq::get(url).send()?;
let bytes = response.as_bytes();
let cursor = Cursor::new(bytes);
let mut zip = zip::ZipArchive::new(cursor)?;
zip.extract(&downloads_path)?;
}
downloaded_websites_path
None
};
query.generate_dts_file(frontend, websites_path.as_path())?;
Some(websites_path)
} else {
None
};
let state = AppState {
query,
frontend,
websites_path,
};
let compression_layer = CompressionLayer::new()
.br(true)
.deflate(true)
.gzip(true)
.zstd(true);
let router = Router::new()
.add_api_routes()
.add_website_routes(frontend)
.route("/version", get(Json(env!("CARGO_PKG_VERSION"))))
.with_state(state)
.layer(compression_layer);
let mut port = 3110;
let mut listener;
loop {
listener = TcpListener::bind(format!("0.0.0.0:{port}")).await;
if listener.is_ok() {
break;
}
port += 1;
Ok(Self(AppState {
query,
frontend,
websites_path,
}))
}
info!("Starting server on port {port}...");
pub async fn serve(self) -> color_eyre::Result<()> {
let state = self.0;
let listener = listener.unwrap();
let compression_layer = CompressionLayer::new()
.br(true)
.deflate(true)
.gzip(true)
.zstd(true);
serve(listener, router).await?;
let router = Router::new()
.add_api_routes()
.add_website_routes(state.frontend)
.route("/version", get(Json(env!("CARGO_PKG_VERSION"))))
.with_state(state)
.layer(compression_layer);
Ok(())
let mut port = 3110;
let mut listener;
loop {
listener = TcpListener::bind(format!("0.0.0.0:{port}")).await;
if listener.is_ok() {
break;
}
port += 1;
}
info!("Starting server on port {port}...");
let listener = listener.unwrap();
serve(listener, router).await?;
Ok(())
}
}
pub fn log_result(code: StatusCode, path: &str, instant: Instant) {
pub fn log_result(code: StatusCode, uri: &Uri, instant: Instant) {
let time = format!("{}µs", instant.elapsed().as_micros());
let time = time.bright_black();
match code {
StatusCode::INTERNAL_SERVER_ERROR => error!("{} {} {}", code.as_u16().red(), path, time),
StatusCode::NOT_MODIFIED => info!("{} {} {}", code.as_u16().bright_black(), path, time),
StatusCode::OK => info!("{} {} {}", code.as_u16().green(), path, time),
_ => error!("{} {} {}", code.as_u16().red(), path, time),
StatusCode::INTERNAL_SERVER_ERROR => error!("{} {} {}", code.as_u16().red(), uri, time),
StatusCode::NOT_MODIFIED => info!("{} {} {}", code.as_u16().bright_black(), uri, time),
StatusCode::OK => info!("{} {} {}", code.as_u16().green(), uri, time),
_ => error!("{} {} {}", code.as_u16().red(), uri, time),
}
}