Skip to content

Commit

Permalink
Merge branch 'main' into aumetra/error-repr
Browse files Browse the repository at this point in the history
  • Loading branch information
aumetra committed Apr 6, 2024
2 parents 73328d5 + dc21019 commit 6b2fa3a
Show file tree
Hide file tree
Showing 8 changed files with 126 additions and 15 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ target-analyzer

# MRF directory
/mrf-modules
/mrf-storage

# Devenv stuff
/result
Expand Down
11 changes: 11 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 5 additions & 2 deletions config.example.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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:
Expand Down
1 change: 1 addition & 0 deletions crates/kitsune-config/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"] }
Expand Down
2 changes: 1 addition & 1 deletion crates/kitsune-config/src/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
3 changes: 2 additions & 1 deletion kitsune/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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",
] }
Expand Down Expand Up @@ -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"]
Expand Down
84 changes: 73 additions & 11 deletions kitsune/src/http/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -34,17 +48,60 @@ 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();
tmp.push_str("/index.html");
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()
Expand Down Expand Up @@ -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 =
Expand All @@ -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))
}

Expand Down
32 changes: 32 additions & 0 deletions kitsune/templates/fallback-fallback.html
Original file line number Diff line number Diff line change
@@ -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>

0 comments on commit 6b2fa3a

Please sign in to comment.