mirror of https://github.com/kitsune-soc/kitsune
NGINX-looking fallback fallback, small improvements (#519)
* small improvements * make fallback work * remove potential boxing, move html into own file * move into separate closure
This commit is contained in:
parent
06a731d1c8
commit
dc2101927d
|
@ -20,6 +20,7 @@ target-analyzer
|
|||
|
||||
# MRF directory
|
||||
/mrf-modules
|
||||
/mrf-storage
|
||||
|
||||
# Devenv stuff
|
||||
/result
|
||||
|
|
|
@ -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]]
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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"] }
|
||||
|
|
|
@ -9,7 +9,7 @@ pub struct Configuration {
|
|||
pub clacks_overhead: Vec<SmolStr>,
|
||||
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<oidc::Configuration>,
|
||||
pub port: u16,
|
||||
|
|
|
@ -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"]
|
||||
|
|
|
@ -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<B>(
|
||||
server_config: &server::Configuration,
|
||||
) -> eyre::Result<Router> {
|
||||
) -> impl Service<
|
||||
http::Request<B>,
|
||||
Response = http::Response<impl HttpBody<Data = Bytes, Error = BoxError>>,
|
||||
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<B>() -> TraceLayer<HttpMakeClassifier, impl MakeSpan<B> + Clone> {
|
||||
TraceLayer::new_for_http().make_span_with(|request: &http::Request<B>| {
|
||||
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<Router> {
|
||||
// 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))
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Welcome to Kitsune!</title>
|
||||
<style>
|
||||
html {
|
||||
color-scheme: light dark;
|
||||
}
|
||||
body {
|
||||
width: 35em;
|
||||
margin: 0 auto;
|
||||
font-family: Tahoma, Verdana, Arial, sans-serif;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Welcome to Kitsune!</h1>
|
||||
<p>
|
||||
If you see this page, the Kitsune fediverse server is successfully
|
||||
installed and working. Further configuration is required.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
For online documentation and support please refer to
|
||||
<a href="http://joinkitsune.org/">joinkitsune.org</a>.<br />
|
||||
Commercial support is available at
|
||||
<a href="#">fuckall nowhere</a>.
|
||||
</p>
|
||||
|
||||
<p><em>Thank you for using Kitsune.</em></p>
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in New Issue