mod config; mod factory; use activitypub_base::{ followers_handler::{followers_handler, following_handler}, inbox::inbox_handler, nodeinfo::{nodeinfo_handler, nodeinfo_well_known_handler}, outbox::outbox_handler, webfinger::webfinger_handler, }; use std::net::SocketAddr; use std::sync::Arc; use tower_http::cors::{AllowOrigin, CorsLayer}; use tracing_subscriber::EnvFilter; #[tokio::main] async fn main() { let cfg = config::Config::from_env(); tracing_subscriber::fmt() .with_env_filter(EnvFilter::from_default_env()) .init(); let infra = factory::build(&cfg).await; // CORS let cors = if cfg.cors_origins.trim() == "*" { CorsLayer::permissive() } else { let origins: Vec = cfg .cors_origins .split(',') .map(|o| o.trim()) .filter_map(|o| o.parse().ok()) .collect(); CorsLayer::new() .allow_origin(AllowOrigin::list(origins)) .allow_methods(tower_http::cors::Any) .allow_headers(tower_http::cors::Any) }; let ap_router = axum::Router::new() .route( "/.well-known/webfinger", axum::routing::get(webfinger_handler), ) .route( "/.well-known/nodeinfo", axum::routing::get(nodeinfo_well_known_handler), ) .route("/nodeinfo/2.0", axum::routing::get(nodeinfo_handler)) .route( "/users/{username}/inbox", axum::routing::post(inbox_handler), ) .route( "/users/{username}/outbox", axum::routing::get(outbox_handler), ) .route( "/users/{username}/followers", axum::routing::get(followers_handler), ) .route( "/users/{username}/following", axum::routing::get(following_handler), ) .layer(infra.ap_service.federation_config().middleware()); let base = presentation::routes::router() .merge(ap_router) .with_state(infra.state) .layer(cors); let addr = format!("{}:{}", cfg.host, cfg.port); tracing::info!("Listening on {addr}"); let listener = tokio::net::TcpListener::bind(&addr).await.unwrap(); if let Some(rate_limit) = cfg.rate_limit { use tower_governor::{governor::GovernorConfigBuilder, GovernorLayer}; // crate: tower_governor // per_millisecond sets the token replenishment interval. // rate_limit = max requests/minute => replenish every (60000 / rate_limit) ms. let ms = (60_000u64).saturating_div(rate_limit as u64).max(1); let governor_conf = Arc::new( GovernorConfigBuilder::default() .per_millisecond(ms) .burst_size(rate_limit) .use_headers() .finish() .expect("valid rate limit config"), ); let limiter = governor_conf.limiter().clone(); tokio::spawn(async move { let mut interval = tokio::time::interval(std::time::Duration::from_secs(60)); loop { interval.tick().await; limiter.retain_recent(); } }); let app = base.layer(GovernorLayer::new(governor_conf)); axum::serve( listener, app.into_make_service_with_connect_info::(), ) .await .unwrap(); } else { axum::serve(listener, base).await.unwrap(); } }