Snap Service
🤔 How does a computer get drunk?
🤣 It takes screenshots!
Shared service to generate PNG/PDF snapshots of OCHA websites.
This service is the result of auditing several internally-maintained PDF/PNG generators within OCHA. We consolidated all the common features into one shared service that is highly available for all properties to use simultaneously. If you want a new feature you are welcome to file a ticket in JIRA in the OPS board (specify SnapService
Component when creating ticket).
💧 Working with Drupal? Use the ocha_snap
module to get started quickly.
Table of Contents
API
You MUST use POST /snap
to request Snaps. We do not serve GET
requests because we want to discourage people hotlinking to Snaps, and also to control bot traffic. If you try to GET /snap
it returns HTTP 405 Method Not Allowed
.
If you still want to use a GET request, you may proxy the request through your server and change the verb to POST
on your web head before passing the request through to the Snap Service. This places the risk of high volume GET
traffic on your server, instead of Snap Service.
POST /snap
Default | Required | Type |
---|---|---|
null | yes | N/A |
Required Parameters
You MUST send ONE of the following (url
or html
).
url
String representing the URL you want to Snap.
Default | Required | Type |
---|---|---|
null | yes¹ | String |
The URL must be valid. The protocol must be included. You may not include authentication in the URL (see user
/pass
parameters for HTTP Basic Auth). If the URL can't be found, Snap Service will return HTTP 400 Bad Request.
html
The URL-encoded HTML you want to render. Send with Content-Type: application/x-www-form-urlencoded
as your encoding.
Default | Required | Type |
---|---|---|
null | yes¹ | String |
¹ EITHER url
or html
are required, but send only one of them! If you do not specify either of these, or you specify both, Snap Service will return HTTP 400 Bad Request
.
service
While it won't affect the output you receive from Snap Service, this parameter allows our Ops team to monitor and report your usage of the shared Snap service. It also allows us to prioritize support/feature requests.
Must be an alphanumeric string (hyphens, underscores are also allowed) such as dsreports
, hr-info
or hid_api
.
Default | Required | Type |
---|---|---|
null | yes | String |
Optional Parameters
Send any combination of the following as querystring parameters. We do our best to validate your input. When found to be invalid, we return HTTP 400 Bad Request
and the response body will be a JSON object containing all failed validations.
output
Specify png
if you want a PNG image or pdf
for PDF.
Default | Required | Type |
---|---|---|
pdf |
no | String |
media
Specify a CSS Media. Options are screen
or print
.
Default | Required | Type |
---|---|---|
screen |
no | String |
width
Specify a pixel value for the viewport width.
The Snap Service implicitly assumes that you are Snapping a responsive website. if you are having problems with layout, it might resolve things to simply specify a wider width
that is similar to a desktop monitor, such as 1280
(with a corresponding height
).
Default | Required | Type |
---|---|---|
800 |
no | integer |
height
Specify a pixel value for the viewport height.
Default | Required | Type |
---|---|---|
600 |
no | integer |
scale
Specify a device scale (pixel density) to control resolution of PNG output.
Default | Required | Type |
---|---|---|
2 |
no | Integer |
pdfFormat
Specify a PDF page format from one of the following options available within Puppeteer:
Letter
: 8.5in x 11inLegal
: 8.5in x 14inTabloid
: 11in x 17inLedger
: 17in x 11inA0
: 33.1in x 46.8inA1
: 23.4in x 33.1inA2
: 16.5in x 23.4inA3
: 11.7in x 16.5inA4
: 8.27in x 11.7inA5
: 5.83in x 8.27inA6
: 4.13in x 5.83in
Default | Required | Type |
---|---|---|
A4 |
no | String |
pdfLandscape
Boolean indicating whether the PDF should be Landscape. Defaults to Portrait.
Default | Required | Type |
---|---|---|
false |
no | Boolean |
pdfBackground
Boolean indicating whether the PDF should print any CSS related to backgrounds. This includes colors, base64-endcoded images that you've supplied, and so forth.
Default | Required | Type |
---|---|---|
false |
no | Boolean |
pdfMarginTop
Specify the PDF margin-top. Override CSS unit using pdfMarginUnit
.
Default | Required | Type |
---|---|---|
0 |
no | Integer |
pdfMarginRight
Specify the PDF margin-right. Override CSS unit using pdfMarginUnit
.
Default | Required | Type |
---|---|---|
0 |
no | Integer |
pdfMarginBottom
Specify the PDF margin-bottom. This is set to a non-zero value to match the majority of our properties which have a common set of info at the bottom of the PDF. You can override the value just like any of the margin params. Override CSS unit using pdfMarginUnit
.
Default | Required | Type |
---|---|---|
64 |
no | Integer |
pdfMarginLeft
Specify the PDF margin-left. Override CSS unit using pdfMarginUnit
.
Default | Required | Type |
---|---|---|
0 |
no | Integer |
pdfMarginUnit
Specify the CSS unit of all PDF margins. Must be one of the following: px
, mm
, cm
, in
.
Default | Required | Type |
---|---|---|
px |
no | String |
pdfHeader
Supply inline HTML/CSS to construct a 100% custom PDF Header. The Puppeteer PDF documentation contains additional information regarding pagination and other metadata you might want to dynamically generate. It's listed under headerTemplate
property.
You MUST URL-encode this parameter or it will probably contain content that will break your request.
Default | Required | Type |
---|---|---|
null | no | String |
pdfFooter
All capabilities, limitations, and documentation references are identical to pdfHeader
. See Puppeteer docs
Default | Required | Type |
---|---|---|
null | no | String |
selector
Specify a CSS selector. Send something very specific, such as an #html-id
. If you send a generic selector that matches many elements on your page, then Snap Service will only return the FIRST element that matches your selector.
⚠️ Due to limitations of Chrome Puppeteer, PDFs cannot render selectors, only whole pages.
Default | Required | Type |
---|---|---|
null | no | String |
logo
Display your site's logo in the header area of each page on your PDF. See Custom Logos section for instructions on adding your logo to this repository.
Default | Required | Type |
---|---|---|
null | no | String |
user
HTTP Basic Authentication username.
Default | Required | Type |
---|---|---|
null | no | String |
pass
HTTP Basic Authentication password.
Default | Required | Type |
---|---|---|
null | no | String |
cookies
String representing browser cookies. Just send the contents of document.cookie
from the client-side and it should work.
Default | Required | Type |
---|---|---|
null | no | String |
ua
String representing the User-Agent making the request. This can come directly from a client, or if you make your Snap request from within a server, use whatever logs you have at your disposal (UA, nginx headers, etc)
Default | Required | Type |
---|---|---|
null | no | String |
delay
Number of milliseconds of additional delay you'd like to add before taking the screenshot. Must be an integer between 0-10000 inclusive.
Default | Required | Type |
---|---|---|
0 |
no | Integer |
debug
Boolean meant as a developer-facing parameter to increase the amount of info seen in the logs.
Default | Required | Type |
---|---|---|
false |
no | Boolean |
block
String containing a comma-separated list of strings to search for within domains. When any string you send is found within a request, it will be blocked (e.g. supplying google
will block all of the following: google.com
, fonts.googleapis.com
, google-analytics.com
).
Default | Required | Type |
---|---|---|
null | no | String |
Headers
X-Forwarded-For
— The remote client address making the request. This allows the snap service to log the address.User-Agent
— The remote user-agent of the client making the request. This value is overridden by theua
parameter, if present.
Using Snap Service on your website
The Snap Service will inject a conditional class on the <html>
element before generating your PNG/PDF request. The class indicates which format is being generated, so you can customize for either one, or both.
html.snap--png .my-selector {
/* custom CSS for PNG snaps */
}
html.snap--pdf .my-selector {
/* custom CSS for PDF snaps */
}
html[class^='snap'] .my-selector {
/* custom CSS for any Snap */
}
This class can be used anywhere in your CSS, including within Media Queries (e.g. @media print
, @media screen and (min-width: 700px)
, etc).
Adding new domains to the allow-list
The shared Snap service now limits which domains it will interact with on dev and production. We maintain an allow-list of hostnames (e.g. unocha.org
). It does not need to be more specific.
If you are receiving HTTP 400 errors about the hostname on Dev, please open an OPS ticket before deploying to production to ensure that everything works.
For local development, you can set the ALLOWED_HOSTNAMES
environment variable in docker-compose.yml
.
Localization
It is up to the requesting service to manage localization of all strings sent to Snap Service. The service is designed to be as agnostic to your website as possible in order to support the broadest set of use-cases. We support a very versatile font-family by default (Roboto) in order to ensure that many character sets are supported.
Custom Logos
While including remote images in the PDF Header/Footer is not supported by Chrome Puppeteer, it is possible to include your site's logo in the header of a PDF. First, make a PR against this repository making the following two changes:
- Add the SVG within the
app/logos
directory. - Edit the
app/logos/_list.json
to include the parameter value you prefer, plus the filename.
{
"ocha": {
"filename": "ocha.svg"
},
"hrinfo": {
"filename": "hr-info.svg"
}
}
Once your PR has been deployed, you can activate your logo on PDF Snaps using the logo
parameter (see API) and the value you entered into logos/_list.json
. The logo can be referenced from within pdfHeader
/pdfFooter
by using the following strings:
__LOGO_SRC__
a base64-encoded string representation of your SVG logo.__LOGO_WIDTH__
the width of your SVG determined by server__LOGO_HEIGHT__
the height of your SVG determined by server
Custom Fonts
It's possible to use a limited set of pre-approved custom fonts in your PDF header and footer. Similar to logos, if you'd like to use a font not listed below, you can submit a PR to this repository in order to check the fonts into version control and expose the font to our server's Chrome instance.
Currently available fonts:
- Roboto (v18)
- Roboto Condensed (v16)