axum = { version = "0.8", features = ["macros"] }
axum-extra = { version = "0.10", features = ["cookie", "query"] }
tokio = { version = "1", features = ["full"] }
-tower = { version = "0.5", features = ["util"] }
+tower = { version = "0.5", features = ["util", "limit", "buffer"] }
tower-http = { version = "0.6", features = ["fs", "trace"] }
tracing = "0.1"
use std::{net::SocketAddr, path::Path};
use axum::{
- Router,
+ BoxError, Router,
+ error_handling::HandleErrorLayer,
extract::{ConnectInfo, Extension, FromRef, Request, State},
http::StatusCode,
middleware::{self, Next},
use clap::Parser;
use config::Config;
use itertools::Itertools;
+use tower::{ServiceBuilder, buffer::BufferLayer, limit::RateLimitLayer};
use tower_http::{
services::{ServeDir, ServeFile},
trace::TraceLayer,
get(services::fragments::recipes_list_fragments),
);
- let html_routes = Router::new()
- .route("/", get(services::home_page))
+ let html_routes_with_rate_limit = Router::new()
+ .route("/signin", post(services::user::sign_in_post))
+ .route("/signup", post(services::user::sign_up_post))
.route(
- "/signup",
- get(services::user::sign_up_get).post(services::user::sign_up_post),
+ "/ask_reset_password",
+ post(services::user::ask_reset_password_post),
)
+ .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(
+ consts::NUMBER_OF_CONCURRENT_HTTP_REQUEST_FOR_RATE_LIMIT,
+ consts::DURATION_FOR_RATE_LIMIT,
+ )),
+ );
+
+ let html_routes = Router::new()
+ .route("/", get(services::home_page))
+ .route("/signup", get(services::user::sign_up_get))
.route("/validation", get(services::user::sign_up_validation))
.route("/revalidation", get(services::user::email_revalidation))
- .route(
- "/signin",
- get(services::user::sign_in_get).post(services::user::sign_in_post),
- )
+ .route("/signin", get(services::user::sign_in_get))
.route("/signout", get(services::user::sign_out))
.route(
"/ask_reset_password",
- get(services::user::ask_reset_password_get)
- .post(services::user::ask_reset_password_post),
+ get(services::user::ask_reset_password_get),
)
.route(
"/reset_password",
"/user/edit",
get(services::user::edit_user_get).post(services::user::edit_user_post),
)
+ .merge(html_routes_with_rate_limit)
.nest("/fragments", fragments_routes)
.route_layer(middleware::from_fn(services::ron_error_to_html));