use axum::http::header::CONTENT_SECURITY_POLICY; use axum::http::{Request, StatusCode}; use axum::middleware::{from_fn, Next}; use axum::Router; use headers::{AccessControlMaxAge, HeaderMapExt}; use hyper::Response; use std::time::Duration; use tower::util::MapResponseLayer; use tower_http::services::{ServeDir, ServeFile}; pub fn static_serve_sw(file: &str) -> Router { Router::new() .nest_service("", ServeFile::new(file)) .layer(MapResponseLayer::new(|mut res: Response<_>| { res.headers_mut() .typed_insert(AccessControlMaxAge::from(Duration::from_secs(60 * 10))); res })) } pub fn static_serve(dir: &str) -> Router { let serve_dir = ServeDir::new(dir); Router::new() .nest_service("", serve_dir) .layer(MapResponseLayer::new(|mut res: Response<_>| { res.headers_mut() .typed_insert(AccessControlMaxAge::from(Duration::from_secs( 60 * 60 * 24 * 7, ))); res })) } pub fn static_serve_svg(dir: &str) -> Router { let serve_dir = ServeDir::new(dir); Router::new() .nest_service("", serve_dir) .layer(from_fn(|req: Request<_>, next: Next| async { if !req.uri().path().ends_with(".svg") { return Err(StatusCode::NOT_FOUND); } Ok(next.run(req).await) })) .layer(MapResponseLayer::new(|mut res: Response<_>| { let headers = res.headers_mut(); headers.typed_insert(AccessControlMaxAge::from(Duration::from_secs( 60 * 60 * 24 * 7, ))); headers.insert( CONTENT_SECURITY_POLICY, "default-src 'none'; style-src 'unsafe-inline'" .parse() .unwrap(), ); res })) }