trillium_html_rewriter/
lib.rs1#![forbid(unsafe_code)]
2#![deny(
3 clippy::dbg_macro,
4 missing_copy_implementations,
5 rustdoc::missing_crate_level_docs,
6 missing_debug_implementations,
7 missing_docs,
8 nonstandard_style,
9 unused_qualifications
10)]
11#![doc = include_str!("../README.md")]
12
13use lol_async::rewrite;
14pub use lol_async::{Settings, html};
15use mime::Mime;
16use std::{
17 fmt::{self, Debug, Formatter},
18 str::FromStr,
19 sync::Arc,
20};
21use trillium::{
22 Body, Conn, Handler,
23 KnownHeaderName::{ContentLength, ContentType},
24};
25
26pub struct HtmlRewriter {
35 settings: Arc<dyn Fn() -> Settings<'static, 'static> + Send + Sync + 'static>,
36}
37
38impl Debug for HtmlRewriter {
39 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
40 f.debug_struct("HtmlRewriter").finish()
41 }
42}
43
44impl Handler for HtmlRewriter {
45 async fn before_send(&self, mut conn: Conn) -> Conn {
46 let html = conn
47 .response_headers()
48 .get_str(ContentType)
49 .and_then(|c| Mime::from_str(c).ok())
50 .map(|m| m.subtype() == "html")
51 .unwrap_or_default();
52
53 if html && let Some(body) = conn.take_response_body() {
54 let reader = rewrite(body, (self.settings)());
55 conn.response_headers_mut().remove(ContentLength); conn.with_body(Body::new_streaming(reader, None))
57 } else {
58 conn
59 }
60 }
61}
62
63impl HtmlRewriter {
64 pub fn new(f: impl Fn() -> Settings<'static, 'static> + Send + Sync + 'static) -> Self {
73 Self {
74 settings: Arc::new(f)
75 as Arc<dyn Fn() -> Settings<'static, 'static> + Send + Sync + 'static>,
76 }
77 }
78}