# Gotenberg PDF Client [![crates.io](https://img.shields.io/crates/v/gotenberg_pdf.svg)](https://crates.io/crates/gotenberg_pdf) [![docs.rs](https://img.shields.io/badge/docs.rs-gotenberg_pdf-green)](https://docs.rs/gotenberg_pdf) [![GitHub Actions](https://github.com/phayes/gotenberg_pdf/actions/workflows/rust.yml/badge.svg)](https://github.com/phayes/gotenberg_pdf/actions) **`gotenberg_pdf`** is a Rust library that provides an easy-to-use interface for interacting with the [Gotenberg API](https://gotenberg.dev/). Gotenberg is a docker-based service for converting HTML, Markdown, URLs, and various documents to PDFs. It uses the Chrome engine to render web content to PDF and the LibreOffice engine to convert documents. ## Features - **URL to PDF**: Generate PDFs directly from a webpage URL. - **HTML to PDF**: Convert raw HTML into a PDF. - **Markdown to PDF**: Render Markdown files into a PDF. - **Document to PDF**: Convert various document formats (e.g., DOCX, PPTX) to PDF using the LibreOffice engine. - **Screenshot**: Capture screenshots of webpages or HTML content. ## Installation Add `gotenberg_pdf` to your `Cargo.toml`: ```toml [dependencies] gotenberg_pdf = "0.5" ``` Ensure you have a running instance of Gotenberg, typically via Docker: ```sh docker run --rm -p 3000:3000 gotenberg/gotenberg:8 ``` **N.B.**: This crate is compatible with Gotenberg version 8. ## Usage Examples ### Convert URL to PDF ```rust use gotenberg_pdf::{Client, WebOptions, PaperFormat}; use tokio; #[tokio::main] async fn main() { // Initialize the client with the Gotenberg server URL let client = Client::new("http://localhost:3000"); // Define optional rendering configurations let mut options = WebOptions::default(); options.set_paper_format(PaperFormat::A4); // Convert a URL to PDF let pdf_bytes = client.pdf_from_url("https://example.com", options).await.unwrap(); } ``` ### Convert HTML to PDF ```rust use gotenberg_pdf::{Client, WebOptions}; use tokio; #[tokio::main] async fn main() { let client = Client::new("http://localhost:3000"); let html_content = r#" My PDF

Hello, PDF!

"#; let options = WebOptions::default(); let pdf_bytes = client.pdf_from_html(html_content, options).await.unwrap(); } ``` ### Convert Markdown to PDF ```rust use gotenberg_pdf::{Client, WebOptions}; use std::collections::HashMap; use tokio; #[tokio::main] async fn main() { let client = Client::new("http://localhost:3000"); // Markdown content let mut markdown_files = HashMap::new(); markdown_files.insert("example.md", "# My Markdown PDF\nThis is a test document."); // HTML template to wrap the markdown let html_template = r#" Markdown PDF {{ toHTML "example.md" }} "#; let options = WebOptions::default(); let pdf_bytes = client.pdf_from_markdown(html_template, markdown_files, options).await.unwrap(); } ``` ### Take a Screenshot of a URL ```rust use gotenberg_pdf::{Client, ScreenshotOptions, ImageFormat}; use tokio; #[tokio::main] async fn main() { let client = Client::new("http://localhost:3000"); let mut options = ScreenshotOptions::default(); options.width = Some(1920); options.height = Some(1080); options.format = Some(ImageFormat::Png); let image_bytes = client.screenshot_url("https://example.com", options).await.unwrap(); println!("Screenshot captured: {} bytes", image_bytes.len()); } ``` ### Convert Document to PDF Using LibreOffice Engine ```rust use gotenberg_pdf::{Client, DocumentOptions}; use tokio; #[tokio::main] async fn main() { let client = Client::new("http://localhost:3000"); let filename = "test_files/example.docx"; let file_content = std::fs::read(filename).expect("Failed to read the file"); let options = DocumentOptions { landscape: Some(false), ..Default::default() }; let pdf_bytes = client.pdf_from_doc(filename, file_content, options).await.unwrap(); } ``` ### Convert HTML to Screenshot Image ```rust use gotenberg_pdf::{Client, ScreenshotOptions, ImageFormat}; use tokio; #[tokio::main] async fn main() { let client = Client::new("http://localhost:3000"); let html_content = r#" Screenshot

Hello, Screenshot!

"#; let mut options = ScreenshotOptions::default(); options.width = Some(800); options.height = Some(600); options.format = Some(ImageFormat::Png); let image_bytes = client.screenshot_html(html_content, options).await.unwrap(); } ``` ### Use the streaming client Requires the `stream` feature to be enabled in your `Cargo.toml`. ```rust use gotenberg_pdf::{StreamingClient, WebOptions}; use futures::StreamExt; // for `next()` use tokio::fs::File; use tokio::io::AsyncWriteExt; #[tokio::main] async fn main() -> Result<(), Box> { let client = StreamingClient::new("http://localhost:3000"); let options = WebOptions::default(); let mut stream = client.pdf_from_url("https://example.com", options).await?; // Create or overwrite the PDF file asynchronously let temp_dir = std::env::temp_dir(); let pdf_path = temp_dir.join("example_com.pdf"); let mut file = File::create(pdf_path).await?; // As we receive chunks, write them directly to disk while let Some(chunk) = stream.next().await { let chunk = chunk?; file.write_all(&chunk).await?; } println!("PDF rendered and saved as example_com.pdf"); Ok(()) } ``` ### Use the blocking client for use without tokio or another async runtime. Requires the `blocking` feature to be enabled in your `Cargo.toml`. ```rust use gotenberg_pdf::{BlockingClient, WebOptions, PaperFormat}; fn main() { // Initialize the client with the Gotenberg server URL let client = BlockingClient::new("http://localhost:3000"); // Define optional rendering configurations let mut options = WebOptions::default(); options.set_paper_format(PaperFormat::A4); // Convert a URL to PDF let pdf_bytes = client.pdf_from_url("https://example.com", options).unwrap(); } ``` ## Configuration Options ### [`WebOptions`] Provides control over the PDF generation process from the Chrome engine. These options can be passed to the following methods: - [`Client::pdf_from_url`] - [`Client::pdf_from_html`] - [`Client::pdf_from_markdown`] | Field Name | Description | Default | |-------------------------------------|--------------------------------------------------|-----------------| | trace_id | Unique trace ID for request | Random UUID | | single_page | Print content on one page | false | | paper_width | Paper width as a [LinearDimention] | 8.5 inches | | paper_height | Paper height as a [LinearDimention] | 11 inches | | margin_top | Top margin as a [LinearDimention] | 0.39 inches | | margin_bottom | Bottom margin as a [LinearDimention] | 0.39 inches | | margin_left | Left margin as a [LinearDimention] | 0.39 inches | | margin_right | Right margin as a [LinearDimention] | 0.39 inches | | prefer_css_page_size | Use CSS-defined page size | false | | generate_document_outline | Embed document outline | false | | print_background | Include background graphics | false | | omit_background | Allow transparency in PDF | false | | landscape | Set page orientation to landscape | false | | scale | Scale of page rendering | 1.0 | | native_page_ranges | [`PageRange`] to print, eg `"1,3,5"`, `"1-4'` | All pages | | header_html | HTML for header content | None | | footer_html | HTML for footer content | None | | wait_delay | Delay before conversion | None | | wait_for_expression | Wait until this JS expression returns true | None | | emulated_media_type | Emulated [`MediaType`] ("screen" or "print") | print | | cookies | Cookies for Chromium | None | | skip_network_idle_events | Ignore network idle events | true | | user_agent | Override default User-Agent header | None | | extra_http_headers | Additional HTTP headers | None | | pdfa | Convert to specific PDF/A [PDFFormat] | None | | pdfua | Enable Universal Access compliance | false | | metadata | PDF metadata | None | | fail_on_http_status_codes | HTTP status codes to fail on, 99's are wild | [499, 599] | | fail_on_resource_http_status_codes | Resource HTTP status codes to fail on | None | | fail_on_resource_loading_failed | Fail if resource loading fails | false | | fail_on_console_exceptions | Fail on Chromium console exceptions | false | Includes the [`WebOptions::set_paper_format`] utlity method for common paper sizes. ### [`ScreenshotOptions`] Provides control over the screenshot generation process from the Chrome engine. These options can be passed to the following method: - [`Client::screenshot_url`] - [`Client::screenshot_html`] - [`Client::screenshot_markdown`] | Field Name | Description | Default | |-------------------------------------|--------------------------------------------------|-----------------| | trace_id | Unique trace ID for request | Random UUID | | width | Device screen width in pixels | 800 | | height | Device screen height in pixels | 600 | | clip | Clip screenshot to device dimensions | false | | format | Image format as an [ImageFormat] | png | | quality | Compression quality (jpeg only, 0-100) | 100 | | omit_background | Generate screenshot with transparency | false | | optimize_for_speed | Optimize image encoding for speed | false | | wait_delay | Delay before taking screenshot | None | | wait_for_expression | Wait until this JS expression returns true | None | | emulated_media_type | Emulated [`MediaType`] ("screen" or "print") | print | | cookies | Cookies for Chromium | None | | skip_network_idle_events | Ignore network idle events | true | | user_agent | Override default User-Agent header | None | | extra_http_headers | Additional HTTP headers | None | | fail_on_http_status_codes | HTTP status codes to fail on, 99's are wild | [499, 599] | | fail_on_resource_http_status_codes | Resource HTTP status codes to fail on | None | | fail_on_resource_loading_failed | Fail if resource loading fails | false | | fail_on_console_exceptions | Fail on Chromium console exceptions | None | ### [`DocumentOptions`] Provides control over the document generation process from the LibreOffice engine. These options can be passed to the following method: - [`Client::pdf_from_doc`] | Field Name | Description | Default | |-------------------------------------|--------------------------------------------------|-----------------| | trace_id | Unique trace ID for request | Random UUID | | password | Password for opening the source file | None | | landscape | Set paper orientation to landscape | false | | native_page_ranges | [`PageRange`] to print, eg `"1,2,3"` or `"1-4"` | All pages | | export_form_fields | Export form fields as widgets | true | | allow_duplicate_field_names | Allow duplicate field names in form fields | false | | export_bookmarks | Export bookmarks to PDF | true | | export_bookmarks_to_pdf_destination | Export bookmarks as named destinations | false | | export_placeholders | Export placeholder fields visual markings only | false | | export_notes | Export notes to PDF | false | | export_notes_pages | Export notes pages (Impress only) | false | | export_only_notes_pages | Export only notes pages | false | | export_notes_in_margin | Export notes in margin | false | | convert_ooo_target_to_pdf_target | Convert `.od[tpgs]` links to `.pdf` | false | | export_links_relative_fsys | Export file:// links as relative | false | | export_hidden_slides | Export hidden slides (Impress only) | false | | skip_empty_pages | Suppress automatically inserted empty pages | false | | add_original_document_as_stream | Add original document as a stream | false | | single_page_sheets | Put each sheet on one page | false | | lossless_image_compression | Use lossless image compression (e.g., PNG) | false | | quality | JPG export quality (1-100) | 90 | | reduce_image_resolution | Reduce image resolution | false | | max_image_resolution | Max resolution DPI. 75, 150, 300, 600 or 1200 | 300 | | pdfa | Convert to specific PDF/A [PDFFormat] | None | | pdfua | Enable Universal Access compliance | false | ## Features ### TLS / HTTPS By default there is no support for HTTPS. If you need TLS, you can enable it by adding one of the following features to your `Cargo.toml`: - `rustls-tls` - Enables TLS / HTTPS support using the `rustls` library. - `native-tls` - Enables TLS / HTTPS support using the native system TLS library. ### HTTP/2 By default there is no HTTP/2 support. HTTP/2 support can be enalbed with the `http2` feature. Even with the feature enabled, HTTP/2 will not be selected unless connecting over HTTPS. If you need HTTP/2 over plain HTTP, you need to make use of [`Client::new_with_client`] and [`reqwest::ClientBuilder::http2_prior_knowledge`]. ### Additional features - `stream` - Enables the streaming client to stream generated PDFs directly to disk or other destinations. - `blocking` - Enables the blocking client for use without tokio or another async runtime. - `zeroize` - Enables zeroizing sensitive data in the client. Enabled by default. ## Web Assembly / Browser Support This crate compiles to `wasm32-unknown-unknown` and is runnable in the browser. In the browser, it will use the built-in browser fetch API to make requests to the Gotenberg server. The `stream`, `blocking`, `rustls-tls` and `native-tls` features are not available on wasm32 or in the browser. Be aware that in the browser, the gotenberg server will need to be behind a proxy that sets the correct CORS headers ('Access-Control-Allow-Origin').