html-to-pdf
html-to-pdf copied to clipboard
Microservice for generating PDF and screenshots from either provided HTML or a URL
HTML to PDF
Microservice for generating PDF and screenshots from either provided HTML or a URL.
Uses puppeteer and
headless-chrome.
Written in typescript
compiled by webpack and
dependencies managed by yarn 3.
Docker file is inspired by zenika/alpine-chrome.
⚠️ Disclaimer: chrome is run with --no-sandbox flag meaning it should NOT be run as a public service.
It's only meant to be run as a microservice in your private network where you control what you are printing.
See puppeteer docs
or zenika/alpine-chrome
why we have --no-sandbox.
Docker Images
You can find prebuilt docker images on dockerhub. Each tag on
github should have corresponding docker image tag on dockerhub. For each commit to main branch a corresponding tag
starting with git- prefix is created. This can be used if you want to use some latest version that was not yet released.
Setup
Project is designed to be run as a docker container. It exposes port 4000 by default but can be configured to use
another port using PORT env variable. After starting container an express server will start listening at this port
providing some HTTP endpoints.
For details on running it locally please scroll to Development section.
Usage
Endpoints:
GET /pdfGET /screenshotPOST /pdfPOST /screenshotGET /metricsGET /checkGET /
Note: only POST methods allow passing html instead of an url. Both url and html are optional meaning if none
is provided about:blank will be printed.
Endpoints Details:
-
GET /pdf?url=<url>&filename=<filename>accepts the following query parameters:
-
url: string, required -
filename: string, optional.
Simplest query can be similar to:
/pdf?url=https://example.com -
-
GET /screenshot?url=<url>&filename=<filename>accepts the following query parameters:
-
url: string, required -
filename: string, optional.
Simplest query can be similar to:
/screenshot?url=https://example.com -
-
POST /pdfa POST accepting JSON body with following parameters:
-
url: string, optional. Publicly accessible url of a page to be captured. -
html: string, optional. HTML page with all resources either embedded or referenced using absolute urls. -
pdfOptions: PDFOptions, optional. See puppeteer docs forpage.pdf()or corresponding sources -
viewport: Viewport, optional. See puppeteer docs forpage.setViewport()or corresponding sources -
waitUntil: string[], optional. See puppeteer docs forpage.waitForNavigation() -
timeout: number, optional. See puppeteer docs forpage.setDefaultNavigationTimeout()
Simplest payload can be similar to:
{"url": "https://example.com"} -
-
POST /screenshota POST accepting JSON body with following parameters:
-
url: string, optional. Publicly accessible url of a page to be captured. -
html: string, optional. HTML page with all resources either embedded or referenced using absolute urls. -
screenshotOptions: ScreenshotOptions, optional. See puppeteer docs forpage.screenshot()or corresponding sources Additionally supports emulating media type viaemulateMediaType: stringoptional property. -
viewport: Viewport, optional. See puppeteer docs forpage.setViewport()or corresponding sources -
waitUntil: string[], optional. See puppeteer docs forpage.waitForNavigation() -
timeout: number, optional. See puppeteer docs forpage.setDefaultNavigationTimeout()
Simplest payload is the same as for the
POST /pdfmethod -
-
GET /metricsExports prometheus metrics.
-
GET /checkPrints a dead simple test PDF file to check if the service is healthy.
-
GET /Prints this readme
Development
We are using taskfile for running local commands. Run task to see a list of available commands.
You can develop locally without the need to run docker container (task run). Puppeteer should automatically pick up chrome
installed locally. The only requirement is to have chrome installed, but you are web developer already using chrome,
aren't you 😉.
Otherwise you can run task run to develop in docker container.
To run docker containers locally you need to create deploy/docker-compose.private.yml and add some useful env vars
(all below are optional):
---
version: "3.8"
services:
printer:
environment:
- SENTRY_DSN=<YOUR_SENTRY_DSN>
- BROWSERLESS=1
If you provide SENTRY_DSN all errors from local env will be reported to sentry.
You can run task run:debug which will start useful
browserless/chrome image. If you provide BROWSERLESS=1 in your
docker compose file printer will start using browserless container instead of bundled chrome.
When using browserless you can also do nice debugging at localhost:3000. Note in such case
chrome versions used in browserless and html-to-pdf itself may diverge.