chrome-aws-lambda icon indicating copy to clipboard operation
chrome-aws-lambda copied to clipboard

[BUG] PDF generation fails with blank error

Open mithundas79 opened this issue 3 years ago • 1 comments

Environment

  • chrome-aws-lambda Version: 5.2.1
  • puppeteer / puppeteer-core Version: 5.2.1
  • OS: Linux
  • Node.js Version: 13.x
  • Lambda / GCF Runtime: nodejs12.x

Expected Behavior

Should create pdf

Current Behavior

I get error

{  error: {} }

Steps to Reproduce

import { APIGatewayProxyHandler } from 'aws-lambda';
import 'source-map-support/register';


import * as handlebars from 'handlebars';
import * as AWS from 'aws-sdk';
import chromium from "chrome-aws-lambda";
import puppeteer from "puppeteer-core";


const createHtml = async (template) => {


  const s3 = new AWS.S3();
    let Bucket = process.env.TEMPLATES_BUCKET;
    let Key = `proposal_template.html`;
    let { Body } = await s3.getObject({ Bucket, Key }).promise()
      .catch(e => Promise.reject(e));
      
    

    let html = Body.toString();

    html = handlebars.compile(html)(template.proposal);

    return html;
  
}


const htmlToPdf = async (html) => {
  let browser: any = null;
  let pdfBuffer: Buffer | null = null;

  try {
    browser = await chromium.puppeteer.launch({
      args: chromium.args,
      defaultViewport: chromium.defaultViewport,
      executablePath: await chromium.executablePath,
      headless: true,
      ignoreHTTPSErrors: true,
    })

    const page = await browser.newPage();
    await page.setContent(html);
      
    pdfBuffer = await page.pdf({
      format: "A4"
    });
  } catch (error) {
    throw error
  } finally {
    if (browser !== null) {
      await browser.close();
    }
  }
  return pdfBuffer;

}
const uploadToS3 = async (pdfBuffer: Buffer, BuketKey) => {
    const s3SecI = new AWS.S3();
    let Bucket = process.env.PROPOSALS_BUCKET;
    let Key = `${BuketKey}.pdf`;
    const s3Data = await s3SecI.upload({ Bucket, Key, Body: pdfBuffer, ACL: 'public-read' }).promise()
      .catch(e => Promise.reject(e));

    return s3Data.Location;
}
export const createHtmlToPdf: APIGatewayProxyHandler = async (event, _context) => {

  const requestBody = JSON.parse(JSON.stringify(event.body));

  const templateData = requestBody.templateData;

  return createHtml(templateData)
    .then((html) => {
      return htmlToPdf(html);
    })
    .then((pdf) => {
      const Key = `${templateData.proposalId}/${templateData.versionId}`;
      return uploadToS3(pdf, Key);
    })
    .then((pdfLink) => {
      return {
        statusCode: 200,
        body: JSON.stringify({
          pdfLink
        }, null, 2)
      };
    })
    .catch((err) => {
      return {
        statusCode: 200,
        body: JSON.stringify({
          message: 'Failed',
          error: err
        }, null, 2)
      };
    })
}

Possible Solution

I checked the createHtml, and uploadToS3 functions separately they works as normal.... but htmlPdf fails. Specifically it fails at

browser = await chromium.puppeteer.launch({
      args: chromium.args,
      defaultViewport: chromium.defaultViewport,
      executablePath: await chromium.executablePath,
      headless: true,
      ignoreHTTPSErrors: true,
    });

mithundas79 avatar Aug 19 '20 13:08 mithundas79

@mithundas79 If the problematic line is indeed what you are saying (browser = await chromium.puppeteer.launch({...) then most of the code you are showing us is likely to be irrelevant. My guess would be that you are having a configuration error / missing dependency, and you cannot launch the browser. That's all.

If that is not the case, please reduce your example because it has too many moving parts.

Hard-code the HTML as a plain string in the JavaScript code. Get rid of everything specific to the Lambda and write the PDF directly to disc by passing a path: '/tmp/myexample.pdf', to the await page.pdf({...}) call. We must be able to test everything locally and without sam.

If that still doesn't reveal where the problem is, try eliminating as much of the HTML and the JavaScript code as possible.

Long story short: Please try to make your example minimal.

baharev avatar Nov 22 '20 13:11 baharev