From 1aa1ec2379fc55229b015ac27ef4c2ceaddac144 Mon Sep 17 00:00:00 2001 From: Clay Smith Date: Fri, 16 Mar 2018 16:10:59 -0700 Subject: [PATCH 1/2] add ability to visit a URL without specifying a script --- index.js | 35 ++++++++++++++++++++++++----------- lib/sandbox.js | 35 ++++++++++++++++++++--------------- 2 files changed, 44 insertions(+), 26 deletions(-) diff --git a/index.js b/index.js index ffde4c1..b48b4c1 100644 --- a/index.js +++ b/index.js @@ -13,6 +13,15 @@ if (!process.env.CLEAN_SESSIONS) { $browser = chromium.createSession(); } +const parseScriptInput = (event) => { + const inputParam = event.Base64Script || process.env.BASE64_SCRIPT; + if (typeof inputParam !== 'string') { + return null + } + + return Buffer.from(inputParam, 'base64').toString('utf8'); +} + exports.handler = (event, context, callback) => { context.callbackWaitsForEmptyEventLoop = false; @@ -34,27 +43,31 @@ exports.handler = (event, context, callback) => { log.info(`Received event: ${JSON.stringify(event, null, 2)}`); - // Read input - const inputParam = event.Base64Script || process.env.BASE64_SCRIPT; - if (typeof inputParam !== 'string') { - return callback('Expected Base64Script string as input.'); - } - - const inputBuffer = Buffer.from(inputParam, 'base64').toString('utf8'); - log.debug(`Executing script "${inputBuffer}"`); - // Creates a new session on each event (instead of reusing for performance benefits) if (process.env.CLEAN_SESSIONS) { $browser = chromium.createSession(); } - sandbox.executeScript(inputBuffer, $browser, webdriver, function(err) { + var opts = { + browser: $browser, + driver: webdriver + }; + + // Provide script: either a 1) selenium script or 2) a URL to visit + var inputBuffer = parseScriptInput(event); + if (inputBuffer !== null) { + opts.scriptText = inputBuffer; + } else if (event.pageUrl || process.env.PAGE_URL) { + opts.pageUrl = event.pageUrl || process.env.PAGE_URL; + } + + sandbox.executeScript(opts, function(err) { if (process.env.LOG_DEBUG) { log.debug(child.execSync('ps aux').toString()); log.debug(child.execSync('cat /tmp/chromedriver.log').toString()) } if (err) { - callback(err, null); + return callback(err, null); } callback(null, 'Finished executing script'); diff --git a/lib/sandbox.js b/lib/sandbox.js index 0759bda..f4d3ba9 100644 --- a/lib/sandbox.js +++ b/lib/sandbox.js @@ -1,7 +1,21 @@ const vm = require('vm'); const log = require('lambda-log'); -exports.executeScript = function(scriptText, browser, driver, cb) { +exports.executeScript = function(opts = {}, cb) { + const browser = opts.browser; + const driver = opts.driver; + var scriptText = opts.scriptText; + + // Just visit a web page if a script isn't specified + if (opts.pageUrl && (typeof scriptText !== 'string')) { + scriptText = `$browser.get('${opts.pageUrl}').then(function(){ $browser.close() });`; + } + log.debug(`Executing script "${scriptText}"`); + + if (typeof scriptText !== 'string') { + return cb('Error: no url or script found to execute.'); + } + // Create Sandbox VM const sandbox = { '$browser': browser, @@ -9,7 +23,7 @@ exports.executeScript = function(scriptText, browser, driver, cb) { 'console': console }; - const script = new vm.Script(scriptText); + const script = new vm.Script(opts.scriptText); // TODO: Set timeout options for VM context const scriptContext = new vm.createContext(sandbox); try { @@ -19,28 +33,19 @@ exports.executeScript = function(scriptText, browser, driver, cb) { return cb(e, null); } - /* - // Print performance logs - $browser.manage().logs().get('performance').then(function (log) { - for (var index in log) { - var entry = log[index]; - console.log("[script-log] [" + entry.level.name + "] " + entry.message); - } - }); - */ // https://github.com/GoogleChrome/puppeteer/issues/1825#issuecomment-372241101 // Reuse existing session, likely some edge cases around this... if (process.env.CLEAN_SESSIONS) { - $browser.quit().then(function() { + browser.quit().then(function() { cb(null); }); } else { browser.manage().deleteAllCookies().then(function() { - return $browser.get('about:blank').then(function() { + return browser.get('about:blank').then(function() { cb(null); - }).catch(function(err) { - cb(err); }); + }).catch(function(err) { + cb(err); }); } } From 91a9638e5597bed8e52c28f7cc4e3daab096dd86 Mon Sep 17 00:00:00 2001 From: Clay Smith Date: Thu, 22 Mar 2018 13:05:55 -0700 Subject: [PATCH 2/2] wrap selenium script console.log output --- index.js | 3 ++- lib/sandbox.js | 19 ++++++++++++++----- lib/visit-page.js | 7 +++++++ 3 files changed, 23 insertions(+), 6 deletions(-) create mode 100644 lib/visit-page.js diff --git a/index.js b/index.js index b48b4c1..08d26c1 100644 --- a/index.js +++ b/index.js @@ -53,7 +53,7 @@ exports.handler = (event, context, callback) => { driver: webdriver }; - // Provide script: either a 1) selenium script or 2) a URL to visit + // Determine script to run: either a 1) base64-encoded selenium script or 2) a URL to visit var inputBuffer = parseScriptInput(event); if (inputBuffer !== null) { opts.scriptText = inputBuffer; @@ -67,6 +67,7 @@ exports.handler = (event, context, callback) => { log.debug(child.execSync('cat /tmp/chromedriver.log').toString()) } if (err) { + log.error(err); return callback(err, null); } diff --git a/lib/sandbox.js b/lib/sandbox.js index f4d3ba9..376cad7 100644 --- a/lib/sandbox.js +++ b/lib/sandbox.js @@ -7,23 +7,32 @@ exports.executeScript = function(opts = {}, cb) { var scriptText = opts.scriptText; // Just visit a web page if a script isn't specified - if (opts.pageUrl && (typeof scriptText !== 'string')) { - scriptText = `$browser.get('${opts.pageUrl}').then(function(){ $browser.close() });`; + if (opts.pageUrl && scriptText === undefined) { + scriptText = require('fs').readFileSync(require('path').join(__dirname, 'visit-page.js'), 'utf8').toString(); } - log.debug(`Executing script "${scriptText}"`); + log.info(`Executing script "${scriptText}"`); if (typeof scriptText !== 'string') { return cb('Error: no url or script found to execute.'); } + var consoleWrapper = { + log: function(){ + var args = Array.prototype.slice.call(arguments); + args.unshift('[lambdium-selenium]'); + console.log.apply(console, args); + } + }; + // Create Sandbox VM const sandbox = { '$browser': browser, '$driver': driver, - 'console': console + '$pageUrl': opts.pageUrl, + 'console': consoleWrapper }; - const script = new vm.Script(opts.scriptText); + const script = new vm.Script(scriptText); // TODO: Set timeout options for VM context const scriptContext = new vm.createContext(sandbox); try { diff --git a/lib/visit-page.js b/lib/visit-page.js new file mode 100644 index 0000000..c97b9c6 --- /dev/null +++ b/lib/visit-page.js @@ -0,0 +1,7 @@ +// This is the default lambdium webdriver script: it just visits a page url. +console.log($pageUrl); +$browser.get($pageUrl).then(function() { + console.log('visited page', $pageUrl); +}).catch(function() { + console.log('error visiting page', $pageUrl); +});