diff --git a/app/lib/pdf.js b/app/lib/pdf.js index a59436e60..78142dbaf 100644 --- a/app/lib/pdf.js +++ b/app/lib/pdf.js @@ -1,11 +1,12 @@ /** * @module pdf */ +const { URL } = require('url'); const config = require('../models/config-model').server; const { BrowserHandler, getBrowser } = require('./headless-browser'); +const browserHandler = new BrowserHandler(); const { timeout } = config.headless; -const { URL } = require('url'); /** * @typedef PdfGetOptions @@ -35,35 +36,52 @@ const DEFAULTS = { * @param {PdfGetOptions} [options] - PDF options * @return { Promise } a promise that returns the PDF */ -async function get(url, options = {}) { +async function get( + url, + { + format = DEFAULTS.FORMAT, + margin = DEFAULTS.MARGIN, + landscape = DEFAULTS.LANDSCAPE, + scale = DEFAULTS.SCALE, + } = {} +) { if (!url) { throw new Error('No url provided'); } - options.format = options.format || DEFAULTS.FORMAT; - options.margin = options.margin || DEFAULTS.MARGIN; - options.landscape = options.landscape || DEFAULTS.LANDSCAPE; - options.scale = options.scale || DEFAULTS.SCALE; - const urlObj = new URL(url); - urlObj.searchParams.append('format', options.format); - urlObj.searchParams.append('margin', options.margin); - urlObj.searchParams.append('landscape', options.landscape); - urlObj.searchParams.append('scale', options.scale); + urlObj.searchParams.append('format', format); + urlObj.searchParams.append('margin', margin); + urlObj.searchParams.append('landscape', landscape); + urlObj.searchParams.append('scale', scale); - const browser = await getBrowser(new BrowserHandler()); + const browser = await getBrowser(browserHandler); const page = await browser.newPage(); let pdf; try { - await page + // To use an eventhandler here and catch a specific error, + // we have to return a Promise (in this case one that never resolves). + const detect401 = new Promise((resolve, reject) => { + page.on('requestfinished', (request) => { + if (request.response().status() === 401) { + const e = new Error('Authentication required'); + e.status = 401; + reject(e); + } + }); + }); + const goToPage = page .goto(urlObj.href, { waitUntil: 'networkidle0', timeout }) .catch((e) => { e.status = /timeout/i.test(e.message) ? 408 : 400; throw e; }); + // Either a 401 error is thrown or goto succeeds (or encounters a real loading error) + await Promise.race([detect401, goToPage]); + /* * This works around an issue with puppeteer not printing canvas * images that were loaded from a file. @@ -93,15 +111,15 @@ async function get(url, options = {}) { }); pdf = await page.pdf({ - landscape: options.landscape, - format: options.format, + landscape, + format, margin: { - top: options.margin, - left: options.margin, - right: options.margin, - bottom: options.margin, + top: margin, + left: margin, + right: margin, + bottom: margin, }, - scale: options.scale, + scale, printBackground: true, }); } catch (e) {