use std::path::PathBuf; use axum::{ body::Body, extract::Request, middleware::Next, response::{IntoResponse, Response}, }; use http::header; pub async fn flatpak_headers_middleware(req: Request, next: Next) -> Response { let path = req.uri().path().to_string(); let mut response = next.run(req).await; // Add content-type for Flatpak metadata files. if path.ends_with(".flatpakrepo") || path.ends_with(".flatpakref") || path == "/config" { response.headers_mut().insert( header::CONTENT_TYPE, "application/octet-stream".parse().unwrap(), ); } // Add cache-control based on OSTree path semantics. let cache_control = if path.starts_with("/objects/") || path.starts_with("/deltas/") || path.starts_with("/extensions/") { // Content-addressed and immutable. "public, immutable, max-age=31536000" } else if path.starts_with("/refs/") { // Refs may change on update. "public, must-revalidate, max-age=60" } else { return response; }; response .headers_mut() .insert(header::CACHE_CONTROL, cache_control.parse().unwrap()); response } pub async fn serve_flatpakrepo(repo_path: PathBuf) -> impl IntoResponse { let path = repo_path.join("flatpakrepo"); match tokio::fs::read_to_string(&path).await { Ok(contents) => ( [(header::CONTENT_TYPE, "application/octet-stream")], contents, ), Err(_) => ( [(header::CONTENT_TYPE, "text/plain")], "No .flatpakrepo file found".to_string(), ), } }