[
  {
    "path": ".gitattributes",
    "content": "layer/headless_shell filter=lfs diff=lfs merge=lfs -text\n"
  },
  {
    "path": ".gitignore",
    "content": "# package directories\nnode_modules\njspm_packages\n\n# Serverless directories\n.serverless\n\n.DS_store\nchrome-aws-lambda\n"
  },
  {
    "path": "README.md",
    "content": "# Serverless Puppeteer using AWS Lambda Layers\n\n<p>\n  <img src=\"https://img.shields.io/badge/version-1.1.0-blue.svg?cacheSeconds=2592000\" />\n  <a href=\"https://twitter.com/rafalwilinski\">\n    <img alt=\"Twitter: rafalwilinski\" src=\"https://img.shields.io/twitter/follow/rafalwilinski.svg?style=social\" target=\"_blank\" />\n  </a>\n</p>\n\n> Recently AWS introduced [Layers](https://aws.amazon.com/about-aws/whats-new/2018/11/aws-lambda-now-supports-custom-runtimes-and-layers/) which enables sharing common code between functions and working with large dependencies (such as headless chrome) much easier.\n\nThis project example returns a screenshot of page requested via `?address=` query parameter.\n\n![Demo](assets/demo.gif?raw=true 'Demo')\n\n### Usage\n\nIt is very important to tell NPM to skip installing chromium from `puppeteer` package. To do so, installing dependencies should be done using this command:\n\n```sh\nPUPPETEER_SKIP_CHROMIUM_DOWNLOAD=1 npm install\n```\n\nor\n\n```sh\nPUPPETEER_SKIP_CHROMIUM_DOWNLOAD=1 yarn\n```\n\nWithout this, your function size would be more than 200MB which is way too much.\n\nAfter that, you can simply deploy your funciton.\n\n```sh\nsls deploy\n\ncurl <DEPLOYED_ENDPOINT>?address=https://google.com\n```\n\nor apply this ARN to your function directly: `arn:aws:lambda:us-east-1:085108115628:layer:chrome:6`\n\n### Bundling latest Chromium on your own\n\nPrerequisites:\n\n- `brotli`\n\n```sh\n./download-latest.sh\n```\n\nCredits for this solution go to [San Kumar](https://github.com/san-kumar)\n\n### Author\n\n👤 **Rafal Wilinski**\n\n- Twitter: [@rafalwilinski](https://twitter.com/rafalwilinski)\n- Github: [@RafalWilinski](https://github.com/RafalWilinski)\n\n### Show your support\n\nGive a ⭐️ if this project helped you!\n"
  },
  {
    "path": "download-latest.sh",
    "content": "#!/bin/bash\n\nset -e\n\nrm -fr chrome-aws-lambda\ngit clone --depth=1 https://github.com/alixaxel/chrome-aws-lambda.git && \\\ncd chrome-aws-lambda && \\\nmake ../layer/chrome.zip\necho 'Layer created successfully!'\n"
  },
  {
    "path": "handler.js",
    "content": "'use strict';\nconst chromium = require('chrome-aws-lambda');\nconst puppeteer = chromium.puppeteer;\n\nmodule.exports.index = async (event, context) => {\n  let browser = null;\n  try {\n    browser = await puppeteer.launch({\n      defaultViewport:{width:1024,height:800},\n      headless: true,\n      executablePath: await chromium.executablePath,\n      args: chromium.args,\n    });\n\n    const page = await browser.newPage();\n    await page.goto(event['queryStringParameters'].address, {\n      waitUntil: ['domcontentloaded', 'networkidle0'],\n    });\n\n    const image = await page.screenshot({\n      clip: { x: 0, y: 0, width: 1024, height: 800 },\n      encoding: 'base64'\n    });\n\n    return {\n      statusCode: 200,\n      body: image,\n      headers: {\n        'Content-Type': 'image/png',\n      },\n      isBase64Encoded: true\n    };\n  } catch (error) {\n    console.error(error);\n    return {\n      statusCode: 500\n    };\n  }\n  finally{\n    if(browser)\n      await browser.close();\n  }\n};\n"
  },
  {
    "path": "layer/.gitkeep",
    "content": ""
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"serverless-puppeteer-layers\",\n  \"version\": \"1.0.0\",\n  \"description\": \"Recently AWS introduced [Layers](https://aws.amazon.com/about-aws/whats-new/2018/11/aws-lambda-now-supports-custom-runtimes-and-layers/) which enables sharing common code between functions and working with large dependencies (such as headless chrome) much easier.\",\n  \"main\": \"handler.js\",\n  \"dependencies\": {\n    \"serverless-apigw-binary\": \"0.4.4\",\n    \"serverless-apigwy-binary\": \"0.1.0\"\n  },\n  \"devDependencies\": {\n    \"chrome-aws-lambda\": \"^1.20.3\",\n    \"puppeteer-core\": \"^1.20.0\"\n  },\n  \"scripts\": {\n    \"deploy\": \"serverless deploy\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/RafalWilinski/serverless-puppeteer-layers.git\"\n  },\n  \"author\": \"Rafal Wilinski\",\n  \"license\": \"MIT\",\n  \"bugs\": {\n    \"url\": \"https://github.com/RafalWilinski/serverless-puppeteer-layers/issues\"\n  },\n  \"homepage\": \"https://github.com/RafalWilinski/serverless-puppeteer-layers#readme\"\n}\n"
  },
  {
    "path": "serverless.yml",
    "content": "service: serverless-puppeteer-layers\n\nprovider:\n  name: aws\n  runtime: nodejs10.x\n\npackage:\n  exclude:\n    - layer/**\n    - chrome-aws-lambda/**\n    - node_modules/chrome-aws-lambda/**\n\nplugins:\n  - serverless-apigw-binary\n  - serverless-apigwy-binary\n\ncustom:\n  apigwBinary:\n    types:\n      - '*/*'\n\nfunctions:\n  puppeteer-orchestrator:\n    handler: handler.index\n    timeout: 30\n    memorySize: 2048\n    events:\n      - http:\n          method: GET\n          path: /screenshot\n          contentHandling: CONVERT_TO_BINARY\n    layers:\n      - { Ref: ChromeLambdaLayer }\n\nlayers:\n  chrome:\n    package:\n      artifact: layer/chrome.zip    \n"
  }
]