refactored main for unit testing
This commit is contained in:
120
src/lib.rs
Normal file
120
src/lib.rs
Normal file
@@ -0,0 +1,120 @@
|
||||
pub mod auth;
|
||||
pub mod db;
|
||||
pub mod errors;
|
||||
pub mod realtime;
|
||||
pub mod routes;
|
||||
|
||||
use crate::errors::APIError;
|
||||
pub use crate::routes::users; // etc
|
||||
use axum::{
|
||||
Extension, Json, Router,
|
||||
extract::DefaultBodyLimit,
|
||||
http::{Method, header},
|
||||
routing::get,
|
||||
};
|
||||
use serde_json::json;
|
||||
use std::sync::Arc;
|
||||
use std::{path::PathBuf, time::Duration};
|
||||
use tower_governor::{GovernorLayer, governor::GovernorConfigBuilder};
|
||||
use tower_http::{
|
||||
cors::{Any, CorsLayer},
|
||||
trace::{DefaultMakeSpan, DefaultOnResponse, TraceLayer},
|
||||
};
|
||||
use tracing::Level;
|
||||
|
||||
const MAX_USERNAME_LENGTH: usize = 35;
|
||||
const MAX_ROOM_NAME_LENGTH: usize = 35;
|
||||
const MAX_UPLOAD_SIZE: usize = 5 * 1024 * 1024; // Not actually used for now
|
||||
|
||||
pub struct AppConfig {
|
||||
pub avatar_dir: PathBuf,
|
||||
pub prohibit_registration: bool,
|
||||
}
|
||||
|
||||
#[derive(clap::Parser, Debug)]
|
||||
#[command(author, version, about, long_about = None)]
|
||||
pub struct Cli {
|
||||
/// Server port
|
||||
#[arg(short, long, default_value = "8080")]
|
||||
pub port: String,
|
||||
|
||||
/// Database URL
|
||||
#[arg(short, long, default_value = "0.0.0.0:5432")]
|
||||
pub database: String,
|
||||
|
||||
/// Data directory path
|
||||
#[arg(short = 'D', long, default_value = "/var/lib/frangipane")]
|
||||
pub data_dir: String,
|
||||
|
||||
/// Whether to disable user registration
|
||||
#[arg(short, long)]
|
||||
pub no_registration: bool,
|
||||
|
||||
/// Verbose mode
|
||||
#[arg(short, long)]
|
||||
pub verbose: bool,
|
||||
}
|
||||
|
||||
/// Create the app with all routes, middleware and extensions
|
||||
pub fn create_app(
|
||||
db_pool: sqlx::PgPool,
|
||||
config: Arc<AppConfig>,
|
||||
messages: realtime::RealtimeMessages,
|
||||
voice: realtime::RealTimeVoices,
|
||||
) -> Router {
|
||||
let governor_conf = GovernorConfigBuilder::default()
|
||||
.burst_size(20)
|
||||
.per_millisecond(250)
|
||||
.finish()
|
||||
.unwrap();
|
||||
|
||||
let governor_limiter = governor_conf.limiter().clone();
|
||||
|
||||
let voice_clone = voice.clone();
|
||||
|
||||
// A separate background task to clean up
|
||||
let interval = Duration::from_secs(60);
|
||||
std::thread::spawn(move || {
|
||||
loop {
|
||||
std::thread::sleep(interval);
|
||||
|
||||
// tracing::info!("rate limiting storage size: {}", governor_limiter.len());
|
||||
governor_limiter.retain_recent();
|
||||
|
||||
voice_clone.retain_active();
|
||||
}
|
||||
});
|
||||
|
||||
let cors = CorsLayer::new()
|
||||
.allow_origin(Any)
|
||||
.allow_methods([Method::GET, Method::POST])
|
||||
.allow_headers([header::AUTHORIZATION, header::CONTENT_TYPE]);
|
||||
|
||||
Router::new()
|
||||
.route("/version", get(get_version))
|
||||
.merge(routes::users::routes())
|
||||
.merge(routes::rooms::routes())
|
||||
.merge(routes::messages::routes())
|
||||
.merge(routes::voice::routes())
|
||||
.merge(routes::friends::routes())
|
||||
.merge(routes::ws::routes())
|
||||
.layer(Extension(db_pool))
|
||||
.layer(Extension(messages))
|
||||
.layer(Extension(voice))
|
||||
.layer(Extension(config))
|
||||
.layer(GovernorLayer::new(governor_conf))
|
||||
.layer(cors)
|
||||
.layer(DefaultBodyLimit::max(1024 * 5 * 100))
|
||||
.layer(
|
||||
TraceLayer::new_for_http()
|
||||
.make_span_with(DefaultMakeSpan::new().level(Level::DEBUG))
|
||||
.on_request(())
|
||||
.on_response(DefaultOnResponse::new().level(Level::DEBUG)),
|
||||
)
|
||||
}
|
||||
|
||||
/// Public route to get current version
|
||||
async fn get_version() -> Result<Json<serde_json::Value>, APIError> {
|
||||
const VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||
Ok(Json(json!({ "version": VERSION })))
|
||||
}
|
||||
Reference in New Issue
Block a user