2022-10-28 22:41:49 +00:00
|
|
|
mod captcha_solutions;
|
|
|
|
mod config;
|
2022-11-01 19:45:06 +00:00
|
|
|
mod errors;
|
2022-10-28 22:41:49 +00:00
|
|
|
mod forms;
|
2022-11-01 23:24:17 +00:00
|
|
|
mod logging;
|
2022-10-28 22:41:49 +00:00
|
|
|
mod mailer;
|
2022-10-26 00:23:55 +00:00
|
|
|
mod routes;
|
2022-11-01 19:45:06 +00:00
|
|
|
mod templates;
|
2022-10-26 00:23:55 +00:00
|
|
|
|
2022-11-01 19:45:06 +00:00
|
|
|
use anyhow::Result;
|
2022-10-31 01:13:42 +00:00
|
|
|
use axum::extract::Extension;
|
|
|
|
use axum::routing::{get, post};
|
2022-11-01 23:24:17 +00:00
|
|
|
use axum::{error_handling::HandleErrorLayer, http::StatusCode, BoxError};
|
2022-10-31 01:13:42 +00:00
|
|
|
use axum::{Router, Server};
|
2022-11-02 19:50:23 +00:00
|
|
|
use axum_extra::routing::SpaRouter;
|
2022-11-01 23:24:17 +00:00
|
|
|
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
|
2022-10-29 17:09:56 +00:00
|
|
|
use std::process;
|
2022-10-31 01:13:42 +00:00
|
|
|
use std::sync::Arc;
|
2022-11-01 23:24:17 +00:00
|
|
|
use std::time::Duration;
|
|
|
|
use tower::buffer::BufferLayer;
|
|
|
|
use tower::limit::RateLimitLayer;
|
|
|
|
use tower::ServiceBuilder;
|
|
|
|
use tower_http::trace::{DefaultOnResponse, TraceLayer};
|
|
|
|
use tracing::Level;
|
|
|
|
use tracing_appender::non_blocking::WorkerGuard;
|
2022-10-31 01:13:42 +00:00
|
|
|
|
2022-11-01 23:24:17 +00:00
|
|
|
async fn init() -> Result<WorkerGuard> {
|
2022-10-29 17:09:56 +00:00
|
|
|
let mut config = config::Config::new()?;
|
2022-10-31 01:13:42 +00:00
|
|
|
let path_prefix = config.path_prefix.clone();
|
|
|
|
let mailer = Arc::new(mailer::Mailer::new(&mut config)?);
|
2022-11-01 23:24:17 +00:00
|
|
|
|
|
|
|
let address = config.socket_address.address;
|
|
|
|
let socket_address = SocketAddr::new(
|
|
|
|
IpAddr::V4(Ipv4Addr::new(
|
|
|
|
address[0], address[1], address[2], address[3],
|
|
|
|
)),
|
|
|
|
config.socket_address.port,
|
|
|
|
);
|
|
|
|
|
|
|
|
let tracing_worker_gurad = logging::init_logger(&config.logging);
|
|
|
|
|
2022-10-31 01:13:42 +00:00
|
|
|
let config = Arc::new(config);
|
|
|
|
let captcha_solutions = Arc::new(captcha_solutions::SharedCaptchaSolutions::new());
|
|
|
|
|
2022-11-02 19:50:23 +00:00
|
|
|
let spa = SpaRouter::new(&format!("{}/static", &path_prefix), "static");
|
|
|
|
|
2022-10-31 01:13:42 +00:00
|
|
|
let routes = Router::new()
|
|
|
|
.route("/", get(routes::index))
|
|
|
|
.route("/submit", post(routes::submit))
|
2022-11-02 19:50:23 +00:00
|
|
|
.route("/success", get(routes::success));
|
|
|
|
|
|
|
|
let app = Router::new()
|
|
|
|
.nest(&path_prefix, routes)
|
|
|
|
.merge(spa)
|
2022-11-01 23:24:17 +00:00
|
|
|
.layer(TraceLayer::new_for_http().on_response(DefaultOnResponse::new().level(Level::INFO)))
|
|
|
|
.layer(
|
|
|
|
ServiceBuilder::new()
|
|
|
|
.layer(HandleErrorLayer::new(|err: BoxError| async move {
|
|
|
|
(
|
|
|
|
StatusCode::INTERNAL_SERVER_ERROR,
|
|
|
|
format!("Unhandled error: {}", err),
|
|
|
|
)
|
|
|
|
}))
|
|
|
|
.layer(BufferLayer::new(1024))
|
|
|
|
.layer(RateLimitLayer::new(2, Duration::from_secs(3))),
|
|
|
|
)
|
2022-10-31 01:13:42 +00:00
|
|
|
.layer(Extension(config))
|
|
|
|
.layer(Extension(mailer))
|
2022-11-01 19:45:06 +00:00
|
|
|
.layer(Extension(captcha_solutions));
|
2022-10-31 01:13:42 +00:00
|
|
|
|
2022-11-01 23:24:17 +00:00
|
|
|
Server::bind(&socket_address)
|
2022-10-31 01:13:42 +00:00
|
|
|
.serve(app.into_make_service())
|
|
|
|
.await
|
|
|
|
.unwrap();
|
2022-10-28 22:41:49 +00:00
|
|
|
|
2022-11-01 23:24:17 +00:00
|
|
|
Ok(tracing_worker_gurad)
|
2022-10-29 17:09:56 +00:00
|
|
|
}
|
|
|
|
|
2022-10-31 01:13:42 +00:00
|
|
|
#[tokio::main]
|
|
|
|
async fn main() {
|
2022-11-01 23:24:17 +00:00
|
|
|
let _tracing_worker_gurad = init().await.unwrap_or_else(|e| {
|
|
|
|
eprintln!("{e:?}");
|
2022-10-29 17:09:56 +00:00
|
|
|
process::exit(1);
|
2022-11-01 23:24:17 +00:00
|
|
|
});
|
2022-10-26 00:23:55 +00:00
|
|
|
}
|