use axum::{ body::Body, http::{header::HeaderName, HeaderValue, Request, StatusCode}, response::{IntoResponse, Response}, }; use std::str; use tower::ServiceExt; use tower_http::services::ServeFile; pub fn text(code: u16, msg: &str) -> Response { (status_code(code), msg.to_owned()).into_response() } pub fn json(code: u16, json: &str) -> Response { let mut res = (status_code(code), json.to_owned()).into_response(); res.headers_mut().insert( HeaderName::from_static("content-type"), HeaderValue::from_static("application/json"), ); res } pub async fn serve(path: &str) -> Response { if !path.chars().any(|c| c == '.') { return text(403, "Invalid file path"); } let path = format!("public{path}"); let file = ServeFile::new(path); let Ok(mut res) = file.oneshot(Request::new(Body::empty())).await else { tracing::error!("Error while fetching file"); return text(500, "Error when fetching file") }; if res.status() != StatusCode::OK { return text(404, "File not found"); } res.headers_mut().insert( HeaderName::from_static("cache-control"), HeaderValue::from_static("max-age=300"), ); res.into_response() } fn status_code(code: u16) -> StatusCode { StatusCode::from_u16(code).map_or(StatusCode::OK, |code| code) }