#![forbid(unsafe_code)]
#![deny(
clippy::dbg_macro,
missing_copy_implementations,
rustdoc::missing_crate_level_docs,
missing_debug_implementations,
missing_docs,
nonstandard_style,
unused_qualifications
)]
#![doc = include_str!("../README.md")]
use lol_async::rewrite;
pub use lol_async::{Settings, html};
use mime::Mime;
use std::{
fmt::{self, Debug, Formatter},
str::FromStr,
sync::Arc,
};
use trillium::{
Body, Conn, Handler,
KnownHeaderName::{ContentLength, ContentType},
};
pub struct HtmlRewriter {
settings: Arc<dyn Fn() -> Settings<'static, 'static> + Send + Sync + 'static>,
}
impl Debug for HtmlRewriter {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.debug_struct("HtmlRewriter").finish()
}
}
impl Handler for HtmlRewriter {
async fn run(&self, mut conn: Conn) -> Conn {
let html = conn
.response_headers()
.get_str(ContentType)
.and_then(|c| Mime::from_str(c).ok())
.map(|m| m.subtype() == "html")
.unwrap_or_default();
if html && let Some(body) = conn.take_response_body() {
let reader = rewrite(body, (self.settings)());
conn.response_headers_mut().remove(ContentLength); conn.with_body(Body::new_streaming(reader, None))
} else {
conn
}
}
}
impl HtmlRewriter {
pub fn new(f: impl Fn() -> Settings<'static, 'static> + Send + Sync + 'static) -> Self {
Self {
settings: Arc::new(f)
as Arc<dyn Fn() -> Settings<'static, 'static> + Send + Sync + 'static>,
}
}
}