use http_body_util::Full; use hyper::body::Bytes; use hyper::header::{ HeaderName, HeaderValue, CACHE_CONTROL, CONTENT_TYPE, LOCATION, }; use hyper::{Response, StatusCode}; use std::collections::HashMap; use crate::controller::error; pub fn with_headers( response: Response>, headers: Vec<(HeaderName, &str)>, ) -> Response> { let mut response = response; let response_headers = response.headers_mut(); for (name, value) in headers { response_headers.insert(name, HeaderValue::from_str(value).unwrap()); } response } pub fn template( assets: &HashMap, templates: &minijinja::Environment<'_>, path: &str, context: minijinja::Value, ) -> Response> { let context = minijinja::context! { ..context, ..minijinja::context! { assets => assets }}; match render_template(templates, path, context) { Ok(template) => with_headers( Response::new(template.into()), vec![(CONTENT_TYPE, "text/html"), (CACHE_CONTROL, "no-cache")], ), Err(err) => { log::error!("ERROR template rendering {}\n{:?}", path, err); server_error( assets, templates, &format!( "Erreur lors de la préparation de la page : {:?}", err ), ) } } } fn render_template( templates: &minijinja::Environment<'_>, name: &str, context: minijinja::Value, ) -> Result { let template = templates.get_template(name)?; template.render(context) } fn server_error( assets: &HashMap, templates: &minijinja::Environment<'_>, msg: &str, ) -> Response> { with_headers( Response::new( error::template(assets, templates, "Erreur serveur", msg).into(), ), vec![(CONTENT_TYPE, "text/html"), (CACHE_CONTROL, "no-cache")], ) } pub fn text(str: String) -> Response> { let mut response = Response::new(str.into()); *response.status_mut() = StatusCode::OK; response } pub fn ok() -> Response> { let mut response = Response::default(); *response.status_mut() = StatusCode::OK; response } pub fn redirect(uri: &str) -> Response> { let mut response = Response::default(); *response.status_mut() = StatusCode::MOVED_PERMANENTLY; with_headers(response, vec![(LOCATION, uri), (CACHE_CONTROL, "no-cache")]) } pub fn not_found() -> Response> { let mut response = Response::default(); *response.status_mut() = StatusCode::NOT_FOUND; response } pub async fn file(filename: &str, content_type: &str) -> Response> { if let Ok(contents) = tokio::fs::read(filename).await { with_headers( Response::new(Full::new(contents.into())), vec![ (CACHE_CONTROL, "max-age=3153600000"), (CONTENT_TYPE, content_type), ], ) } else { not_found() } }