Headless Chrome and Rust

Darin Gordon

RustNYC - July 2019

Headless Chrome

  • Released in June 2017
  • Exposes Chrome functionality through an API

- Websockets using DevTools Protocol

  • VERY useful collection of tools

- Command line

Use Cases

  • Screenshots

  • Render PDF

Automated Testing

  • Visual Regression Testing
  • Workflow Testing

Miscellaneous Services

Driving the Browser

  • Scraping

 Headless Chrome Clients

  • Authored by Google
  • Written in NodeJS
  • User-friendly, intuitive API
  • The official reference client

 Headless Chrome Clients

Pyppeteer

rust-headless-chrome

Some languages ported the API really well

(and others did it their own way)

rust-headless-chrome

  • Port of Puppeteer to Rust
  • Project began OSS in early 2019
  • Several features, yet far from feature parity with Puppeteer
  • Generate screenshots and PDFs of pages

unofficial logo

rust-headless-chrome

API in a nutshell

Create a Browser instance

Spawn a Tab off of the Browser

Use Tab to navigate and perform actions

rust-headless-chrome

PDF Generation


    let browser = Browser::connect(chrome_url)?;
    
    let tab = browser.wait_for_initial_tab()?;
    
    let local_pdf = tab
        .navigate_to(&uri)?
        .wait_until_navigated()?
        .print_to_pdf(pdf_options)?;
    
    fs::write("report.pdf", &local_pdf)?;

rust-headless-chrome

Screen Snapshot


    let browser = Browser::default()?;
    let tab = browser.wait_for_initial_tab()?;
    tab.navigate_to("https://www.wikipedia.org")?;
    tab.wait_for_element("input#searchInput")?;
    
    let jpeg_data = tab.capture_screenshot(
                        ScreenshotFormat::JPEG(Some(75)),
                        None,
                        true)?;
    
    fs::write("page.jpg", &jpeg_data)?;

Use Case: PDF Report-Generating Service

A Docker-powered stateless API for converting HTML, Markdown and Office documents to PDF.

Gotenberg

  • I didn't need this functionality
  • Web server, headless chrome, and process monitoring all in a single Docker image

1.7GB Docker Image, 1GB+ stripped

Use Case: PDF Report-Generating Service

  • Just renders pdfs from uploaded web files
  • Uses actix-web framework
  • Secured using bearer auth

So... I wrote my own service in Rust!

Use Case: PDF Report-Generating Service

So... I wrote my own service in Rust! (continued)

musl cross-compiled static exec binary:

9.7MB

headless chrome + alpine:

309MB

15.3MB

service binary + alpine:

(headless chrome is the bottleneck)

Use Case: PDF Report-Generating Service

So... I wrote my own service in Rust! (continued)

Would you like to walk through the code together next time?

Until Then..

Questions?

Headless Chrome and Rust

By Darin Gordon

Headless Chrome and Rust

  • 1,177