Skip to content

Instantly share code, notes, and snippets.

@denghongcai
Created January 5, 2025 06:19
Show Gist options
  • Save denghongcai/09b516b5d915e67aff23b5c95becfe53 to your computer and use it in GitHub Desktop.
Save denghongcai/09b516b5d915e67aff23b5c95becfe53 to your computer and use it in GitHub Desktop.
lol-html stream latency test
use lol_html::html_content::Element;
use lol_html::{element, HtmlRewriter, Settings};
use std::io;
use std::io::prelude::*;

fn rewrite_url_in_attr(el: &mut Element<'_, '_>, attr_name: &str) {
    let attr = el
        .get_attribute(attr_name)
        .unwrap()
        .replace("http://", "https://");

    el.set_attribute(attr_name, &attr).unwrap();
}

fn main() {
    let stdin = io::stdin();
    let mut stdout = io::stdout();

    // Use stdout as an output sink for the rewriter
    let output_sink = |c: &[u8]| {
        stdout.write_all(c).unwrap();
        io::stdout().flush().expect("Unable to flush stdout");
    };

    // Create the rewriter
    let mut rewriter = HtmlRewriter::new(
        Settings {
            element_content_handlers: vec![
                element!("a[href], link[rel=stylesheet][href]", |el| {
                    rewrite_url_in_attr(el, "href");
                    Ok(())
                }),
                element!(
                    "script[src], iframe[src], img[src], audio[src], video[src]",
                    |el| {
                        rewrite_url_in_attr(el, "src");
                        Ok(())
                    }
                ),
            ],
            ..Settings::new()
        },
        output_sink,
    );

    // Feed chunks from the stdin to the rewriter
    loop {
        let mut stdin = stdin.lock();
        let buffer = stdin.fill_buf().unwrap();
        let len = buffer.len();

        if len > 0 {
            rewriter.write(buffer).unwrap();
            stdin.consume(len);
        } else {
            rewriter.end().unwrap();
            break;
        }
    }
}
// HTTP Server
const http = require('http');
const url = require('url');

const server = http.createServer((req, res) => {
  const queryObject = url.parse(req.url, true).query;
  const interval = parseInt(queryObject.interval) || 1000;
  const chunkContent = queryObject.chunk || 'Hello, world!';

  res.writeHead(200, { 'Content-Type': 'text/plain' });

  const intervalId = setInterval(() => {
    res.write(chunkContent);
  }, interval);

  req.on('close', () => {
    clearInterval(intervalId);
    res.end();
  });
});

server.listen(3000, () => {
  console.log('Server is listening on port 3000');
});

test command

curl -N http://127.0.0.1:3000\?chunk\=\>\<a  2>/dev/null | cargo run

It will wait until the tagging process is complete and then swiftly print at one-second intervals.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment