schickling / chromeless

🖥 Chrome automation made simple. Runs locally or headless on AWS Lambda.
https://chromeless.netlify.com
MIT License
13.25k stars 575 forks source link

How to run chromeless directly (no proxy) in AWS Lambda + serverless? #452

Closed jaimeiniesta closed 6 years ago

jaimeiniesta commented 6 years ago

Hello, I'm trying to set up an AWS Lambda function with serverless that has an endpoint, accepts an url and returns an screenshot URL.

I could find examples on setting up AWS Lambda to be used with a proxy, but are there examples on how to embed this for direct use in a AWS Lambda function?

My first attempt was including the chromeless dependency in package.json, run npm install from a Docker instance (so that it gets the linux binaries), and upload a function that basically does this:

module.exports.chromelessScreenshot = (event, context, callback) => {
  const { Chromeless } = require('chromeless')

  async function run() {
    const chromeless = new Chromeless()

    const screenshot = await chromeless
      .goto('http://jaimeiniesta.com')
      .screenshot()

    console.log(screenshot) // prints local file path or S3 url

    await chromeless.end()
  }

  run().catch(console.error.bind(console))

  const response = {
    statusCode: 200,
    headers: {
      'Access-Control-Allow-Origin': '*',
    },
    body: JSON.stringify({
      message: "Screenshot"
    }),
  };

  callback(null, response);
};

But when I execute it, I see this error in the logs:

which: no google-chrome-stable in (/var/lang/bin:/usr/local/bin:/usr/bin/:/bin)
which: no google-chrome in (/var/lang/bin:/usr/local/bin:/usr/bin/:/bin)
which: no chromium-browser in (/var/lang/bin:/usr/local/bin:/usr/bin/:/bin)
which: no chromium in (/var/lang/bin:/usr/local/bin:/usr/bin/:/bin)
2018-07-02 13:12:17.094 (+02:00)    c6f5c40a-7de8-11e8-b81d-f38153716708    Error: The environment variable CHROME_PATH must be set to executable of a build of Chromium version 54.0 or later.
    at Object.linux (/var/task/node_modules/chrome-launcher/dist/chrome-finder.js:108:15)
    at Launcher.<anonymous> (/var/task/node_modules/chrome-launcher/dist/chrome-launcher.js:139:80)
    at Generator.throw (<anonymous>)
    at rejected (/var/task/node_modules/chrome-launcher/dist/chrome-launcher.js:10:65)
    at <anonymous>
    at process._tickDomainCallback (internal/process/next_tick.js:228:7)

It looks like Chrome can't be found, what is the PATH for the Chrome binary?

Thanks!

felipetpin commented 6 years ago

Having the same issue here!

jaimeiniesta commented 6 years ago

For the record, I finally changed to use chrome-aws-lambda and puppeteer instead. Check out comments and links here:

https://github.com/jaimeiniesta/serverless-axe-cli/pull/1

nerdmax commented 6 years ago

I was having the same issue. There is a workaround for that. You can run two projects, one is running the serverless example and the other one is running your business logic by connecting to the chrome which is hosting in your first project. Personally speaking, I'm in favour of this solution cause you don't need to deploy the whole chrome application to server everytime you change your business logic. Deploying chrome is like a pre set up, you just need to do it once and use its service.

Details: Project 1: Deploying Chromeless Proxy service to AWS

Get endpointUrl and apiKey

Project 2: Running your business logic:

const Chromeless = require('chromeless').default

async function run() {
  const chromeless = new Chromeless({
    remote: {
      endpointUrl: 'https://XXXXXXXXXX.execute-api.eu-west-1.amazonaws.com/dev',
      apiKey: 'your-api-key-here'
    },
  })

  const screenshot = await chromeless
    .goto('https://www.google.com')
    .type('chromeless', 'input[name="q"]')
    .press(13)
    .wait('#resultStats')
    .screenshot()

  console.log(screenshot) // prints local file path or S3 url

  await chromeless.end()
}

run().catch(console.error.bind(console))

Please leave your comments if anyone has a better solution