Skip to content

Commit d0b99c1

Browse files
Reuse StreamProcessor to handle compression
1 parent a8220b9 commit d0b99c1

2 files changed

Lines changed: 232 additions & 98 deletions

File tree

crates/common/src/creative.rs

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,10 @@
3939
4040
use crate::http_util::compute_encrypted_sha256_token;
4141
use crate::settings::Settings;
42+
use crate::streaming_processor::StreamProcessor;
4243
use crate::tsjs;
4344
use lol_html::{element, html_content::ContentType, text, HtmlRewriter, Settings as HtmlSettings};
45+
use std::io;
4446

4547
// Helper: normalize to absolute URL if http/https or protocol-relative. Otherwise None.
4648
// Checks against the rewrite blacklist to exclude configured domains/patterns from proxying.
@@ -478,6 +480,84 @@ pub fn rewrite_creative_html(markup: &str, settings: &Settings) -> String {
478480
String::from_utf8(out).unwrap_or_else(|_| markup.to_string())
479481
}
480482

483+
/// Stream processor for creative HTML that rewrites URLs to first-party proxy.
484+
///
485+
/// This processor buffers input chunks and processes the complete HTML document
486+
/// when the stream ends, using `rewrite_creative_html` internally.
487+
pub struct CreativeHtmlProcessor {
488+
settings: Settings,
489+
buffer: Vec<u8>,
490+
}
491+
492+
impl CreativeHtmlProcessor {
493+
/// Create a new HTML processor with the given settings.
494+
pub fn new(settings: &Settings) -> Self {
495+
Self {
496+
settings: settings.clone(),
497+
buffer: Vec::new(),
498+
}
499+
}
500+
}
501+
502+
impl StreamProcessor for CreativeHtmlProcessor {
503+
fn process_chunk(&mut self, chunk: &[u8], is_last: bool) -> Result<Vec<u8>, io::Error> {
504+
self.buffer.extend_from_slice(chunk);
505+
506+
if is_last {
507+
let markup = String::from_utf8(std::mem::take(&mut self.buffer))
508+
.map_err(|e| io::Error::other(format!("Invalid UTF-8 in HTML: {}", e)))?;
509+
510+
let rewritten = rewrite_creative_html(&markup, &self.settings);
511+
Ok(rewritten.into_bytes())
512+
} else {
513+
Ok(Vec::new())
514+
}
515+
}
516+
517+
fn reset(&mut self) {
518+
self.buffer.clear();
519+
}
520+
}
521+
522+
/// Stream processor for CSS that rewrites url() references to first-party proxy.
523+
///
524+
/// This processor buffers input chunks and processes the complete CSS
525+
/// when the stream ends, using `rewrite_css_body` internally.
526+
pub struct CreativeCssProcessor {
527+
settings: Settings,
528+
buffer: Vec<u8>,
529+
}
530+
531+
impl CreativeCssProcessor {
532+
/// Create a new CSS processor with the given settings.
533+
pub fn new(settings: &Settings) -> Self {
534+
Self {
535+
settings: settings.clone(),
536+
buffer: Vec::new(),
537+
}
538+
}
539+
}
540+
541+
impl StreamProcessor for CreativeCssProcessor {
542+
fn process_chunk(&mut self, chunk: &[u8], is_last: bool) -> Result<Vec<u8>, io::Error> {
543+
self.buffer.extend_from_slice(chunk);
544+
545+
if is_last {
546+
let css = String::from_utf8(std::mem::take(&mut self.buffer))
547+
.map_err(|e| io::Error::other(format!("Invalid UTF-8 in CSS: {}", e)))?;
548+
549+
let rewritten = rewrite_css_body(&css, &self.settings);
550+
Ok(rewritten.into_bytes())
551+
} else {
552+
Ok(Vec::new())
553+
}
554+
}
555+
556+
fn reset(&mut self) {
557+
self.buffer.clear();
558+
}
559+
}
560+
481561
#[cfg(test)]
482562
mod tests {
483563
use super::{rewrite_creative_html, rewrite_srcset, rewrite_style_urls, to_abs};

0 commit comments

Comments
 (0)