From dc2101927dbdb423dccf0713ee859cf07f332dad Mon Sep 17 00:00:00 2001 From: Aumetra Weisman Date: Sat, 6 Apr 2024 18:41:29 +0200 Subject: [PATCH] NGINX-looking fallback fallback, small improvements (#519) * small improvements * make fallback work * remove potential boxing, move html into own file * move into separate closure --- .gitignore | 1 + Cargo.lock | 11 ++++ config.example.toml | 7 +- crates/kitsune-config/Cargo.toml | 1 + crates/kitsune-config/src/server.rs | 2 +- kitsune/Cargo.toml | 3 +- kitsune/src/http/mod.rs | 84 ++++++++++++++++++++---- kitsune/templates/fallback-fallback.html | 32 +++++++++ 8 files changed, 126 insertions(+), 15 deletions(-) create mode 100644 kitsune/templates/fallback-fallback.html diff --git a/.gitignore b/.gitignore index 21db890ff..aa9afd2ef 100644 --- a/.gitignore +++ b/.gitignore @@ -20,6 +20,7 @@ target-analyzer # MRF directory /mrf-modules +/mrf-storage # Devenv stuff /result diff --git a/Cargo.lock b/Cargo.lock index 74a6ce581..ca85b0bc9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3110,6 +3110,15 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" +[[package]] +name = "human-size" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9994b79e8c1a39b3166c63ae7823bb2b00831e2a96a31399c50fe69df408eaeb" +dependencies = [ + "serde", +] + [[package]] name = "humansize" version = "2.1.3" @@ -3731,6 +3740,7 @@ name = "kitsune-config" version = "0.0.1-pre.6" dependencies = [ "eyre", + "human-size", "isolang", "serde", "smol_str", @@ -8073,6 +8083,7 @@ dependencies = [ "tower-layer", "tower-service", "tracing", + "uuid", ] [[package]] diff --git a/config.example.toml b/config.example.toml index 10f2be03c..233e7b9d4 100644 --- a/config.example.toml +++ b/config.example.toml @@ -139,6 +139,10 @@ type = "in-process" [mrf] module-dir = "mrf-modules" +[mrf.storage] +type = "fs" +path = "./mrf-storage" + # OIDC configuration # # Kitsune can use an OIDC service to manage logins @@ -184,8 +188,7 @@ frontend-dir = "./kitsune-fe/dist" # Maximum upload size # # This is the limit of data that the HTTP server accepts before it returns an HTTP 413 error -# The unit is bytes -max-upload-size = 5242880 # 5MB +max-upload-size = "5MiB" # Enable the media proxy # # The media proxy will relay all of the media streams through the backend, enabling two important properties: diff --git a/crates/kitsune-config/Cargo.toml b/crates/kitsune-config/Cargo.toml index 158fa4f43..3bfe66c1b 100644 --- a/crates/kitsune-config/Cargo.toml +++ b/crates/kitsune-config/Cargo.toml @@ -7,6 +7,7 @@ license.workspace = true [dependencies] eyre = "0.6.12" +human-size = { version = "0.4.3", features = ["serde"] } isolang = { version = "2.4.0", features = ["serde"] } serde = { version = "1.0.197", features = ["derive"] } smol_str = { version = "0.2.1", features = ["serde"] } diff --git a/crates/kitsune-config/src/server.rs b/crates/kitsune-config/src/server.rs index 9a9018555..add01c7e9 100644 --- a/crates/kitsune-config/src/server.rs +++ b/crates/kitsune-config/src/server.rs @@ -9,7 +9,7 @@ pub struct Configuration { pub clacks_overhead: Vec, pub deny_brave_browsers: bool, pub frontend_dir: SmolStr, - pub max_upload_size: usize, + pub max_upload_size: human_size::Size, pub media_proxy_enabled: bool, pub oidc: Option, pub port: u16, diff --git a/kitsune/Cargo.toml b/kitsune/Cargo.toml index 4def0ed3f..0e61ddb57 100644 --- a/kitsune/Cargo.toml +++ b/kitsune/Cargo.toml @@ -91,12 +91,14 @@ thiserror = "1.0.58" time = "0.3.34" tokio = { version = "1.37.0", features = ["full"] } tokio-util = { version = "0.7.10", features = ["compat"] } +tower = { version = "0.4.13", features = ["util"] } tower-stop-using-brave = { path = "../lib/tower-stop-using-brave" } tower-x-clacks-overhead = { path = "../lib/tower-x-clacks-overhead" } tower-http = { version = "0.5.2", features = [ "catch-panic", "cors", "fs", + "request-id", "timeout", "trace", ] } @@ -141,7 +143,6 @@ redis = { version = "0.25.2", default-features = false, features = [ "connection-manager", "tokio-comp", ] } -tower = "0.4.13" [features] default = ["graphql-api", "mastodon-api"] diff --git a/kitsune/src/http/mod.rs b/kitsune/src/http/mod.rs index 7682d256a..8a113524c 100644 --- a/kitsune/src/http/mod.rs +++ b/kitsune/src/http/mod.rs @@ -5,23 +5,37 @@ use self::{ openapi::api_docs, }; use crate::state::Zustand; -use axum::{extract::DefaultBodyLimit, Router}; +use axum::{ + body::HttpBody, + extract::DefaultBodyLimit, + response::{Html, IntoResponse}, + Router, +}; +use bytes::Bytes; use color_eyre::eyre::{self, Context}; use cursiv::CsrfLayer; +use http::{HeaderName, StatusCode}; +use http_body_util::Either; use kitsune_config::server; -use std::time::Duration; +use std::{convert::Infallible, time::Duration}; use tokio::net::TcpListener; +use tower::{BoxError, Service, ServiceExt}; use tower_http::{ catch_panic::CatchPanicLayer, cors::CorsLayer, + request_id::{MakeRequestUuid, PropagateRequestIdLayer, SetRequestIdLayer}, services::{ServeDir, ServeFile}, timeout::TimeoutLayer, - trace::TraceLayer, + trace::{HttpMakeClassifier, MakeSpan, TraceLayer}, }; use tower_stop_using_brave::StopUsingBraveLayer; use tower_x_clacks_overhead::XClacksOverheadLayer; use utoipa_swagger_ui::SwaggerUi; +const FALLBACK_FALLBACK_INDEX: &str = include_str!("../../templates/fallback-fallback.html"); + +static X_REQUEST_ID: HeaderName = HeaderName::from_static("x-request-id"); + #[cfg(feature = "graphql-api")] mod graphql; mod handler; @@ -34,10 +48,18 @@ mod util; pub mod extractor; -pub fn create_router( - state: Zustand, +#[inline] +fn serve_frontend( server_config: &server::Configuration, -) -> eyre::Result { +) -> impl Service< + http::Request, + Response = http::Response>, + Error = Infallible, + Future = impl Send, +> + Clone +where + B: Send + 'static, +{ let frontend_dir = &server_config.frontend_dir; let frontend_index_path = { let mut tmp = frontend_dir.to_string(); @@ -45,6 +67,41 @@ pub fn create_router( tmp }; + let handle_response = |response: http::Response<_>| { + if response.status() == StatusCode::NOT_FOUND { + (StatusCode::NOT_FOUND, Html(FALLBACK_FALLBACK_INDEX)) + .into_response() + .map(Either::Left) + } else { + response.map(Either::Right) + } + }; + + ServeDir::new(frontend_dir.as_str()) + .fallback(ServeFile::new(frontend_index_path)) + .map_future(move |result_fut| async move { + let result = result_fut.await; + result.map(handle_response) + }) +} + +#[inline] +fn trace_layer() -> TraceLayer + Clone> { + TraceLayer::new_for_http().make_span_with(|request: &http::Request| { + debug_span!( + "request", + method = %request.method(), + uri = %request.uri(), + version = ?request.version(), + request_id = ?request.headers().get(&X_REQUEST_ID).unwrap(), + ) + }) +} + +pub fn create_router( + state: Zustand, + server_config: &server::Configuration, +) -> eyre::Result { // This warning will come up if the server is compiled without the Mastodon API compatibility #[allow(unused_mut)] let mut router = Router::new() @@ -78,9 +135,7 @@ pub fn create_router( router = router .merge(SwaggerUi::new("/swagger-ui").url("/api-doc/openapi.json", api_docs())) - .fallback_service( - ServeDir::new(frontend_dir.as_str()).fallback(ServeFile::new(frontend_index_path)), - ); + .fallback_service(serve_frontend(server_config)); if !server_config.clacks_overhead.is_empty() { let clacks_overhead_layer = @@ -98,11 +153,18 @@ pub fn create_router( .layer(CatchPanicLayer::new()) .layer(CorsLayer::permissive()) .layer(CsrfLayer::generate()) // TODO: Make this configurable instead of random - .layer(DefaultBodyLimit::max(server_config.max_upload_size)) + .layer(DefaultBodyLimit::max( + server_config.max_upload_size.to_bytes() as usize, + )) .layer(TimeoutLayer::new(Duration::from_secs( server_config.request_timeout_secs, ))) - .layer(TraceLayer::new_for_http()) + .layer(trace_layer()) + .layer(PropagateRequestIdLayer::new(X_REQUEST_ID.clone())) + .layer(SetRequestIdLayer::new( + X_REQUEST_ID.clone(), + MakeRequestUuid, + )) .with_state(state)) } diff --git a/kitsune/templates/fallback-fallback.html b/kitsune/templates/fallback-fallback.html new file mode 100644 index 000000000..45211a2c9 --- /dev/null +++ b/kitsune/templates/fallback-fallback.html @@ -0,0 +1,32 @@ + + + + Welcome to Kitsune! + + + +

Welcome to Kitsune!

+

+ If you see this page, the Kitsune fediverse server is successfully + installed and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + joinkitsune.org.
+ Commercial support is available at + fuckall nowhere. +

+ +

Thank you for using Kitsune.

+ +