Skip to content
This repository has been archived by the owner on Jun 12, 2024. It is now read-only.

Commit

Permalink
fixed: if pdf page encounters a 401 response this will be API response,
Browse files Browse the repository at this point in the history
kobotoolbox#688

fixed: a headless chrome instance will now be kept alive at all times so pdf responses should be quicker
  • Loading branch information
MartijnR committed Jul 12, 2023
1 parent 7f68bda commit e8321ed
Showing 1 changed file with 38 additions and 20 deletions.
58 changes: 38 additions & 20 deletions app/lib/pdf.js
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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) {
Expand Down

0 comments on commit e8321ed

Please sign in to comment.