Crate html2pdf_api

Crate html2pdf_api 

Source
Expand description

§html2pdf-api

Thread-safe browser pool for headless Chrome automation with web framework integration.

This crate provides a production-ready browser pool that manages headless Chrome/Chromium instances with automatic lifecycle management, health monitoring, and graceful shutdown.

§Features

  • Connection Pooling: Reuses browser instances to avoid expensive startup costs
  • Health Monitoring: Background thread continuously checks browser health
  • TTL Management: Automatically retires old browsers and creates replacements
  • Race-Free Design: Careful lock ordering prevents deadlocks
  • Graceful Shutdown: Clean termination of all background tasks
  • RAII Pattern: Automatic return of browsers to pool via Drop
  • Web Framework Integration: Optional support for Actix-web, Rocket, and Axum

§Architecture

┌─────────────────────────────────────────────┐
│         Your Web Application                │
│      (Actix-web / Rocket / Axum)            │
└─────────────────┬───────────────────────────┘
                  │
                  ▼
┌─────────────────────────────────────────────┐
│              BrowserPool                    │
│ ┌─────────────────────────────────────────┐ │
│ │   Available Pool (idle browsers)        │ │
│ │   [Browser1] [Browser2] [Browser3]      │ │
│ └─────────────────────────────────────────┘ │
│ ┌─────────────────────────────────────────┐ │
│ │   Active Tracking (in-use browsers)     │ │
│ │   {id → Browser}                        │ │
│ └─────────────────────────────────────────┘ │
│ ┌─────────────────────────────────────────┐ │
│ │   Keep-Alive Thread                     │ │
│ │   (health checks + TTL enforcement)     │ │
│ └─────────────────────────────────────────┘ │
└─────────────────────────────────────────────┘
                  │
                  ▼
┌─────────────────────────────────────────────┐
│        Headless Chrome Browsers             │
│     (managed by headless_chrome crate)      │
└─────────────────────────────────────────────┘

§Quick Start

use html2pdf_api::prelude::*;
use std::time::Duration;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Create pool with custom configuration
    let pool = BrowserPool::builder()
        .config(
            BrowserPoolConfigBuilder::new()
                .max_pool_size(5)
                .warmup_count(3)
                .browser_ttl(Duration::from_secs(3600))
                .build()?
        )
        .factory(Box::new(ChromeBrowserFactory::with_defaults()))
        .build()?;

    // Warmup the pool (recommended for production)
    pool.warmup().await?;

    // Use browsers
    {
        let browser = pool.get()?;
        let tab = browser.new_tab()?;
        tab.navigate_to("https://example.com")?;
        // ... generate PDF, take screenshot, etc.
    } // Browser automatically returned to pool

    // Graceful shutdown
    pool.shutdown_async().await;

    Ok(())
}

§Environment Configuration

When the env-config feature is enabled, you can initialize the pool from environment variables (loaded from app.env file or system environment):

use html2pdf_api::init_browser_pool;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let pool = init_browser_pool().await?;
    // pool is Arc<Mutex<BrowserPool>>, ready for web handlers
    Ok(())
}

§Environment File

Create an app.env file in your project root (not .env for better cross-platform visibility):

BROWSER_POOL_SIZE=5
BROWSER_WARMUP_COUNT=3
BROWSER_TTL_SECONDS=3600

§Environment Variables

VariableTypeDefaultDescription
BROWSER_POOL_SIZEusize5Maximum browsers in pool
BROWSER_WARMUP_COUNTusize3Browsers to pre-create
BROWSER_TTL_SECONDSu643600Browser lifetime (seconds)
BROWSER_WARMUP_TIMEOUT_SECONDSu6460Warmup timeout
BROWSER_PING_INTERVAL_SECONDSu6415Health check interval
BROWSER_MAX_PING_FAILURESu323Failures before removal
CHROME_PATHStringautoCustom Chrome binary path

§Feature Flags

FeatureDescription
env-configEnable environment-based configuration
actix-integrationActix-web framework integration
rocket-integrationRocket framework integration
axum-integrationAxum framework integration
test-utilsEnable mock factory for testing

§Web Framework Integration

§Actix-web

use actix_web::{web, App, HttpServer};
use html2pdf_api::prelude::*;

async fn generate_pdf(
    pool: web::Data<Arc<Mutex<BrowserPool>>>,
) -> impl Responder {
    let pool = pool.lock().unwrap();
    let browser = pool.get()?;
    // ... use browser
}

§Rocket

use rocket::State;
use html2pdf_api::prelude::*;

#[get("/pdf")]
async fn generate_pdf(
    pool: &State<Arc<Mutex<BrowserPool>>>,
) -> Result<Vec<u8>, Status> {
    let pool = pool.lock().unwrap();
    let browser = pool.get()?;
    // ... use browser
}

§Axum

use axum::{Extension, response::IntoResponse};
use html2pdf_api::prelude::*;

async fn generate_pdf(
    Extension(pool): Extension<Arc<Mutex<BrowserPool>>>,
) -> impl IntoResponse {
    let pool = pool.lock().unwrap();
    let browser = pool.get()?;
    // ... use browser
}

§Error Handling

All fallible operations return Result<T, BrowserPoolError>. The error type provides context about what went wrong:

use html2pdf_api::{BrowserPool, BrowserPoolError};

match pool.get() {
    Ok(browser) => {
        // Use browser
    }
    Err(BrowserPoolError::ShuttingDown) => {
        // Pool is shutting down, handle gracefully
    }
    Err(BrowserPoolError::BrowserCreation(msg)) => {
        // Chrome failed to launch
        eprintln!("Browser creation failed: {}", msg);
    }
    Err(e) => {
        // Other errors
        eprintln!("Pool error: {}", e);
    }
}

§Testing

For testing without Chrome, enable the test-utils feature and use MockBrowserFactory:

use html2pdf_api::factory::mock::MockBrowserFactory;

let factory = MockBrowserFactory::always_fails("Test error");
let pool = BrowserPool::builder()
    .factory(Box::new(factory))
    .enable_keep_alive(false)
    .build()?;

Re-exports§

pub use config::BrowserPoolConfig;
pub use config::BrowserPoolConfigBuilder;
pub use error::BrowserPoolError;
pub use error::Result;
pub use factory::BrowserFactory;
pub use factory::ChromeBrowserFactory;
pub use factory::create_chrome_options;
pub use handle::BrowserHandle;
pub use pool::BrowserPool;
pub use pool::BrowserPoolBuilder;
pub use stats::PoolStats;
pub use traits::Healthcheck;
pub use config::env::chrome_path_from_env;
pub use config::env::from_env;
pub use pool::init_browser_pool;

Modules§

config
Configuration for browser pool behavior and limits.
error
Error types for the browser pool.
factory
Browser factory implementations.
handle
RAII handle for browser instances.
integrations
Web framework integrations.
pool
Browser pool with lifecycle management.
prelude
Convenient imports for common usage patterns.
service
Core PDF generation service.
stats
Pool statistics for monitoring and health checks.
traits
Traits for abstraction and extensibility.

Type Aliases§

SharedBrowserPool
Shared browser pool type for web frameworks.