use headers::HeaderMapExt;
use hyper::{Body, Request, Response};
use std::path::Path;
use crate::{
Error, fs::meta::try_markdown_variant, handler::RequestHandlerOpts, headers_ext::Accept,
};
pub(crate) fn pre_process<T>(req: &Request<T>, base_path: &Path, uri_path: &str) -> Option<String> {
let accepts_markdown = req
.headers()
.typed_get::<Accept>()
.map(|accept| accept.accepts_markdown())
.unwrap_or(false);
if !accepts_markdown {
return None;
}
let mut file_path = base_path.to_path_buf();
let sanitized_path = uri_path.trim_start_matches('/');
if !sanitized_path.is_empty() {
file_path.push(sanitized_path);
}
let md_path = try_markdown_variant(&file_path)?;
tracing::info!("markdown: found variant {:?}", md_path);
md_path
.strip_prefix(base_path)
.ok()
.and_then(|p| p.to_str())
.map(|s| format!("/{}", s))
}
pub(crate) fn post_process(
is_markdown_variant: bool,
opts: &RequestHandlerOpts,
mut resp: Response<Body>,
) -> Result<Response<Body>, Error> {
if !is_markdown_variant || !opts.accept_markdown {
return Ok(resp);
}
if let Ok(content_type) = "text/markdown; charset=utf-8".parse() {
resp.headers_mut()
.insert(hyper::header::CONTENT_TYPE, content_type);
}
Ok(resp)
}
#[cfg(test)]
mod tests {
use super::*;
use hyper::{Body, Request};
#[test]
fn test_no_accept_header() {
let req = Request::builder()
.method("GET")
.uri("/test")
.body(Body::empty())
.unwrap();
let base_path = std::path::Path::new("/tmp");
let result = pre_process(&req, base_path, "/test");
assert!(result.is_none());
}
#[test]
fn test_accepts_html_only() {
let req = Request::builder()
.method("GET")
.uri("/test")
.header("Accept", "text/html")
.body(Body::empty())
.unwrap();
let base_path = std::path::Path::new("/tmp");
let result = pre_process(&req, base_path, "/test");
assert!(result.is_none());
}
#[test]
fn test_accepts_markdown_no_file() {
let req = Request::builder()
.method("GET")
.uri("/test")
.header("Accept", "text/markdown")
.body(Body::empty())
.unwrap();
let base_path = std::path::Path::new("/tmp");
let result = pre_process(&req, base_path, "/test");
assert!(result.is_none());
}
}