Add hyper convinience layers

This commit is contained in:
Tristan D. 2025-03-24 02:31:36 +01:00
parent 96258b500a
commit 9c75092d12
Signed by: tristan
SSH key fingerprint: SHA256:9oFM1J63hYWJjCnLG6C0fxBS15rwNcWwdQNMOHYKJ/4
7 changed files with 114 additions and 13 deletions

64
Cargo.lock generated
View file

@ -1246,6 +1246,8 @@ dependencies = [
"rust-embed",
"serde",
"tokio",
"tower 0.5.2",
"tower-http 0.6.2",
"tracing",
"tracing-subscriber",
]
@ -2282,6 +2284,16 @@ dependencies = [
"hashbrown 0.14.5",
]
[[package]]
name = "hdrhistogram"
version = "7.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "765c9198f173dd59ce26ff9f95ef0aafd0a0fe01fb9d72841bc5066a4c06511d"
dependencies = [
"byteorder",
"num-traits",
]
[[package]]
name = "heck"
version = "0.4.1"
@ -2785,6 +2797,16 @@ version = "2.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130"
[[package]]
name = "iri-string"
version = "0.7.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dbc5ebe9c3a1a7a5127f920a418f7585e9e758e911d0466ed004f393b0e380b2"
dependencies = [
"memchr",
"serde",
]
[[package]]
name = "itertools"
version = "0.12.1"
@ -3182,7 +3204,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34"
dependencies = [
"cfg-if",
"windows-targets 0.48.5",
"windows-targets 0.52.6",
]
[[package]]
@ -3293,7 +3315,7 @@ dependencies = [
"tokio",
"tokio-stream",
"tower 0.4.13",
"tower-http",
"tower-http 0.5.2",
"tracing",
"tracing-subscriber",
"tracing-test",
@ -3328,7 +3350,7 @@ dependencies = [
"thiserror 1.0.69",
"tokio",
"tower 0.4.13",
"tower-http",
"tower-http 0.5.2",
"tracing",
"tracing-subscriber",
"uuid",
@ -6370,9 +6392,14 @@ checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9"
dependencies = [
"futures-core",
"futures-util",
"hdrhistogram",
"indexmap 2.8.0",
"pin-project-lite",
"slab",
"sync_wrapper",
"tokio",
"tokio-stream",
"tokio-util",
"tower-layer",
"tower-service",
"tracing",
@ -6405,6 +6432,37 @@ dependencies = [
"tracing",
]
[[package]]
name = "tower-http"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "403fa3b783d4b626a8ad51d766ab03cb6d2dbfc46b1c5d4448395e6628dc9697"
dependencies = [
"async-compression",
"base64 0.22.1",
"bitflags 2.9.0",
"bytes",
"futures-core",
"futures-util",
"http 1.3.1",
"http-body",
"http-body-util",
"http-range-header",
"httpdate",
"iri-string",
"mime",
"mime_guess",
"percent-encoding",
"pin-project-lite",
"tokio",
"tokio-util",
"tower 0.5.2",
"tower-layer",
"tower-service",
"tracing",
"uuid",
]
[[package]]
name = "tower-layer"
version = "0.3.3"

View file

@ -24,6 +24,8 @@ mime_guess = "2.0.5"
rust-embed = { version = "8.5.0", features = ["axum", "compression"] }
serde = { version = "1.0", features = ["derive"] }
tokio = { version = "1.43", features = ["full", "tracing"] }
tower = { version = "0.5.2", features = ["full", "tokio", "tokio-stream"] }
tower-http = { version = "0.6.2", features = ["full"] }
tracing = { version = "0.1.41", features = [
"max_level_debug",
"release_max_level_info",

File diff suppressed because one or more lines are too long

View file

@ -1,14 +1,18 @@
mod assets;
mod ui;
use std::sync::Once;
use std::{iter::once, sync::Once};
use assets::AssetsController;
use axum::{
http::{StatusCode, Uri},
response::IntoResponse,
routing::get,
};
use axum::{http, response::IntoResponse, routing::get};
use http::Response;
use hypertext::{maud, GlobalAttributes, Renderable};
use tower_http::{
compression::CompressionLayer,
propagate_header::PropagateHeaderLayer,
sensitive_headers::SetSensitiveRequestHeadersLayer,
set_header::SetResponseHeaderLayer,
trace::TraceLayer,
};
use ui::UiController;
use crate::ui::html_elements;
@ -33,9 +37,9 @@ fn markup_405() -> impl Renderable {
}
}
async fn handle_404(uri: Uri) -> impl IntoResponse {
async fn handle_404(uri: http::Uri) -> impl IntoResponse {
(
StatusCode::NOT_FOUND,
http::StatusCode::NOT_FOUND,
axum::response::Html(markup_404(format!("{uri:?}")).render()),
)
.into_response()
@ -43,7 +47,7 @@ async fn handle_404(uri: Uri) -> impl IntoResponse {
async fn handle_405() -> impl IntoResponse {
(
StatusCode::METHOD_NOT_ALLOWED,
http::StatusCode::METHOD_NOT_ALLOWED,
axum::response::Html(markup_405().render()),
)
.into_response()
@ -82,6 +86,17 @@ async fn main() {
// TODO pick free port/config
let listener = tokio::net::TcpListener::bind("0.0.0.0:8000").await.unwrap();
fn content_length_from_response<B>(response: &Response<B>) -> Option<http::HeaderValue>
where
B: axum::body::HttpBody,
{
response
.body()
.size_hint()
.exact()
.map(|size| http::HeaderValue::from_str(&size.to_string()).unwrap())
}
tracing::info!("Listening on http://0.0.0.0:8000");
let router: axum::Router = axum::Router::new()
@ -89,6 +104,16 @@ async fn main() {
.merge(AssetsController::into_router(app_state.clone()))
.fallback_service(get(handle_404))
.method_not_allowed_fallback(handle_405)
// High level logging of requests and responses
.layer(TraceLayer::new_for_http())
// Mark the `Authorization` request header as sensitive so it doesn't show in logs
.layer(SetSensitiveRequestHeadersLayer::new(once(http::header::AUTHORIZATION)))
// Compress responses
.layer(CompressionLayer::new())
// Propagate `X-Request-Id`s from requests to responses
.layer(PropagateHeaderLayer::new(http::HeaderName::from_static("x-request-id")))
// If the response has a known size set the `Content-Length` header
.layer(SetResponseHeaderLayer::overriding(http::header::CONTENT_TYPE, content_length_from_response))
.with_state(app_state);
let _ = axum::serve(listener, router.into_make_service()).await;

View file

@ -112,7 +112,14 @@ line-height: inherit; }
}
/* layer: default */
.static{position:static;}
.m-1{margin:0.25rem;}
.m-2{margin:0.5rem;}
.m-3{margin:0.75rem;}
.m-4{margin:1rem;}
.m-5{margin:1.25rem;}
.m-6{margin:1.5rem;}
.m-7{margin:1.75rem;}
.m-8{margin:2rem;}
.mx-auto{margin-left:auto;margin-right:auto;}
.mb-2{margin-bottom:0.5rem;}
.mb-4{margin-bottom:1rem;}
@ -128,9 +135,14 @@ line-height: inherit; }
.bg-blue-500{--un-bg-opacity:1;background-color:rgb(59 130 246 / var(--un-bg-opacity)) /* #3b82f6 */;}
.bg-gray-100{--un-bg-opacity:1;background-color:rgb(243 244 246 / var(--un-bg-opacity)) /* #f3f4f6 */;}
.bg-white{--un-bg-opacity:1;background-color:rgb(255 255 255 / var(--un-bg-opacity)) /* #fff */;}
.p-1{padding:0.25rem;}
.p-2{padding:0.5rem;}
.p-3{padding:0.75rem;}
.p-4{padding:1rem;}
.p-5{padding:1.25rem;}
.p-6{padding:1.5rem;}
.p-7{padding:1.75rem;}
.p-8{padding:2rem;}
.text-2xl{font-size:1.5rem;line-height:2rem;}
.text-white{--un-text-opacity:1;color:rgb(255 255 255 / var(--un-text-opacity)) /* #fff */;}
.font-bold{font-weight:700;}

View file

@ -14,6 +14,9 @@ import { presetHeroPatterns } from '@julr/unocss-preset-heropatterns';
import { presetExtra } from 'unocss-preset-extra';
export default defineConfig({
safelist: [
...["p-", "m-"].map((v)=> Array.from({ length: 8 }, (_, i: number) => `${v}${i + 1}`))
],
content: {
filesystem: [
"**/*.{html,css,scss,rs}",

View file

@ -181,6 +181,7 @@
sqlx-cli
unzip
rocmPackages.rocminfo
tailwindcss
]
++ buildInputs;