diff --git a/.nowignore b/.nowignore index bce4d8977..78812a213 100644 --- a/.nowignore +++ b/.nowignore @@ -36,6 +36,7 @@ build/Release node_modules/ jspm_packages/ /packages/*/node_modules +*/node_modules # Typescript v1 declaration files typings/ @@ -55,38 +56,21 @@ typings/ # Yarn Integrity file .yarn-integrity -# Mapped Docker Volumes +# docker docker-data/ +.docker-config/ # dotenv environment variables file *.env +.env* .DS_Store -servers/republik/seeds/seeds.json -servers/republik/seeds/comments.json -servers/republik/local/ -servers/publikator/seeds/seeds.json - -# now -.docker-config +# only lambdas .github -servers/republik -servers/publikator -packages/apollo-modules-node -packages/access -packages/base -packages/collections -packages/discussions -packages/documents -packages/election -packages/env -packages/mail -packages/notifications -packages/preview -packages/schedulers -packages/search -packages/slack -packages/sms -packages/voting - +.travis* +docker* +Procfile* +servers/ +packages/ +*.sql diff --git a/lambdas/chromium/.env.example b/lambdas/chromium/.env.example new file mode 100644 index 000000000..951ecf8f9 --- /dev/null +++ b/lambdas/chromium/.env.example @@ -0,0 +1,8 @@ +# render urls must start with the following prefix +#URL_WHITELIST=https://www.republik.ch +# provide all allow any url +URL_WHITELIST=all + +# optional: the chrome for puppeteer to connect to (if chrome-aws-lambda is not available) +#PUPPETEER_WS_ENDPOINT= + diff --git a/lambdas/chromium/README.md b/lambdas/chromium/README.md new file mode 100644 index 000000000..4f1d923e3 --- /dev/null +++ b/lambdas/chromium/README.md @@ -0,0 +1,40 @@ +# @orbiting/lambdas-chromium + +API to puppeteer - chromium. + +[screenshot.js](screenshots.js) is a NodeJS [request](https://nodejs.org/api/http.html#http_event_request)-[response](https://nodejs.org/api/http.html#http_class_http_serverresponse)-handler to generate screenshots. + +[puppeteer]('https://github.com/GoogleChrome/puppeteer') tries to use locally available chromium (by [chrome-aws-lambda](https://github.com/alixaxel/chrome-aws-lambda)) otherwise tries to fall back to connect to `PUPPETEER_WS_ENDPOINT` + + +## ENVs + +see [.env.example] + +``` +now secret url_whitelist https://www.republik.ch,https://republik.ch +now -e URL_WHITELIST=@url_whitelist +``` + + +## Endpoints +- screenshot.js + - example query: `/?url=:url&[width=[:w]x[:h]]&[zoomFactor=:sf]&[fullPage=:fp]&[cookie=:c]&[basicAuthUser=:u]&[basicAuthPass=:p]` + - renders ?url + - optional &width &height + - default 1200x1 + - optional &fullPage + - default true + - this api screenshots the full page per default (with scrolling), set `fullPage` to `'false'` or `'0'` to crop to viewport + - optional &zoomFactor + - requires viewport or w/h + - default 1 + - optional &cookie + - example: 'id=208h2n' + - optionsl &basicAuthUser &basicAuthPass + - send basic auth on opening urls + + +## Credits + +Inspired by: [now-examples puppeteer-screenshot](https://github.com/zeit/now-examples/tree/master/puppeteer-screenshot) diff --git a/lambdas/chromium/package.json b/lambdas/chromium/package.json new file mode 100644 index 000000000..ebc366b99 --- /dev/null +++ b/lambdas/chromium/package.json @@ -0,0 +1,21 @@ +{ + "name": "@orbiting/lambdas-chromium", + "version": "0.0.1", + "description": "headless chrome providing screenshots", + "main": "index.js", + "repository": { + "type": "git", + "url": "git+https://github.com/orbiting/backends.git" + }, + "author": "Patrick Recher ", + "license": "AGPL-3.0", + "bugs": { + "url": "https://github.com/orbiting/backends/issues" + }, + "homepage": "https://github.com/orbiting/backends#readme", + "dependencies": { + "chrome-aws-lambda": "^1.12.0", + "debug": "^3.1.0", + "puppeteer-core": "^1.12.2" + } +} diff --git a/lambdas/chromium/screenshot.js b/lambdas/chromium/screenshot.js new file mode 100644 index 000000000..b8639c9fa --- /dev/null +++ b/lambdas/chromium/screenshot.js @@ -0,0 +1,125 @@ +const puppeteer = require('puppeteer-core') +const chromium = require('chrome-aws-lambda') +const { parse } = require('url') +const debug = require('debug')('screenshot') + +const { + URL_WHITELIST, + PUPPETEER_WS_ENDPOINT +} = process.env + +const DEFAULT_WIDTH = 1200 +const DEFAULT_HEIGHT = 1 +const DEFAULT_SCALE_FACTOR = 1 + +if (!URL_WHITELIST) { + console.warn('missing env URL_WHITELIST, the /render endpoint will not work') +} +const whitelistedUrls = URL_WHITELIST && URL_WHITELIST.split(',') + +const getBrowser = async () => { + if (chromium.headless) { + debug('rendering with local headless chrome') + return puppeteer.launch({ + args: chromium.args, + executablePath: await chromium.executablePath, + headless: chromium.headless + }) + } else { + if (!PUPPETEER_WS_ENDPOINT) { + console.warn('missing env PUPPETEER_WS_ENDPOINT, cannot render') + return + } + debug(`rendering with chromium @ PUPPETEER_WS_ENDPOINT`) + return puppeteer.connect({ + browserWSEndpoint: PUPPETEER_WS_ENDPOINT + }) + } +} + +const getPosInt = (number) => + Math.ceil(Math.abs(number)) + +// returns buffer +module.exports = async (req, res) => { + const { + query: { + url, + width, + height, + zoomFactor, + fullPage = true, + type = 'png', + quality, + cookie, + basicAuthUser, + basicAuthPass + } + } = parse(req.url, true) + debug({ url, width, height, zoomFactor, fullPage }) + + if (!url) { + res.statusCode = 422 + return res.end('missing url param') + } + + const allowed = + (URL_WHITELIST && URL_WHITELIST === 'all') || + (whitelistedUrls && !!whitelistedUrls.find(whiteUrl => url.indexOf(whiteUrl) === 0)) + + if (!allowed) { + console.warn('unauthorized render url requested: ' + url) + res.statusCode = 403 + return res.end() + } + + try { + const browser = await getBrowser() + + const page = await browser.newPage() + + const promises = [ + page.setViewport({ + width: getPosInt(width) || DEFAULT_WIDTH, + height: getPosInt(height) || DEFAULT_HEIGHT, + deviceScaleFactor: Math.abs(zoomFactor) || DEFAULT_SCALE_FACTOR + }), + page.setExtraHTTPHeaders({ 'DNT': '1' }) + ] + + if (cookie) { + const [name, value] = cookie.split('=') + promises.push( + page.setCookie({ name, value, url }) + ) + } + + await Promise.all(promises) + + await page.goto(url) + + if (basicAuthUser) { + await page.authenticate({ + username: basicAuthUser, + password: basicAuthPass + }) + } + + const screenshot = await page.screenshot({ + fullPage: !(['false', '0'].includes(fullPage)), + type, + ...quality !== undefined + ? { quality: getPosInt(quality) } + : {} + }) + + browser.close() + + res.statusCode = 200 + res.setHeader('Content-Type', `image/${type}`) + return res.end(screenshot) + } catch (error) { + res.statusCode = 500 + return res.end(error.message || error) + } +} diff --git a/lambdas/chromium/yarn.lock b/lambdas/chromium/yarn.lock new file mode 100644 index 000000000..cbe0d5890 --- /dev/null +++ b/lambdas/chromium/yarn.lock @@ -0,0 +1,292 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +agent-base@^4.1.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.2.1.tgz#d89e5999f797875674c07d87f260fc41e83e8ca9" + integrity sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg== + dependencies: + es6-promisify "^5.0.0" + +async-limiter@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.0.tgz#78faed8c3d074ab81f22b4e985d79e8738f720f8" + integrity sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg== + +balanced-match@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" + integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +buffer-from@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" + integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== + +chrome-aws-lambda@^1.12.0: + version "1.12.0" + resolved "https://registry.yarnpkg.com/chrome-aws-lambda/-/chrome-aws-lambda-1.12.0.tgz#49649d5127f5afc111e33a27a667148f8103da9e" + integrity sha512-U3ArUMQ9+Z0dk7fog+CltQEnLGx5+pF4N7aBN3nRddwv6H9lmkxgZo8zw0oTxwLWm2a/5g/B0/bOR2qR0kTrEw== + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= + +concat-stream@1.6.2: + version "1.6.2" + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" + integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== + dependencies: + buffer-from "^1.0.0" + inherits "^2.0.3" + readable-stream "^2.2.2" + typedarray "^0.0.6" + +core-util-is@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= + +debug@2.6.9: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + +debug@^3.1.0: + version "3.2.6" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" + integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== + dependencies: + ms "^2.1.1" + +debug@^4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" + integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== + dependencies: + ms "^2.1.1" + +es6-promise@^4.0.3: + version "4.2.6" + resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.6.tgz#b685edd8258886365ea62b57d30de28fadcd974f" + integrity sha512-aRVgGdnmW2OiySVPUC9e6m+plolMAJKjZnQlCwNSuK5yQ0JN61DZSO1X1Ufd1foqWRAlig0rhduTCHe7sVtK5Q== + +es6-promisify@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203" + integrity sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM= + dependencies: + es6-promise "^4.0.3" + +extract-zip@^1.6.6: + version "1.6.7" + resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-1.6.7.tgz#a840b4b8af6403264c8db57f4f1a74333ef81fe9" + integrity sha1-qEC0uK9kAyZMjbV/Txp0Mz74H+k= + dependencies: + concat-stream "1.6.2" + debug "2.6.9" + mkdirp "0.5.1" + yauzl "2.4.1" + +fd-slicer@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.0.1.tgz#8b5bcbd9ec327c5041bf9ab023fd6750f1177e65" + integrity sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU= + dependencies: + pend "~1.2.0" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= + +glob@^7.1.3: + version "7.1.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" + integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +https-proxy-agent@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz#51552970fa04d723e04c56d04178c3f92592bbc0" + integrity sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ== + dependencies: + agent-base "^4.1.0" + debug "^3.1.0" + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@^2.0.3, inherits@~2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= + +isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= + +mime@^2.0.3: + version "2.4.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.0.tgz#e051fd881358585f3279df333fe694da0bcffdd6" + integrity sha512-ikBcWwyqXQSHKtciCcctu9YfPbFYZ4+gbHEmE0Q8jzcTYQg5dHCr3g2wwAZjPoJfQVXZq6KXAjpXOTf5/cjT7w== + +minimatch@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== + dependencies: + brace-expansion "^1.1.7" + +minimist@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" + integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= + +mkdirp@0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" + integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= + dependencies: + minimist "0.0.8" + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= + +ms@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" + integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== + +once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= + dependencies: + wrappy "1" + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= + +pend@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" + integrity sha1-elfrVQpng/kRUzH89GY9XI4AelA= + +process-nextick-args@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa" + integrity sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw== + +progress@^2.0.1: + version "2.0.3" + resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" + integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== + +proxy-from-env@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.0.0.tgz#33c50398f70ea7eb96d21f7b817630a55791c7ee" + integrity sha1-M8UDmPcOp+uW0h97gXYwpVeRx+4= + +puppeteer-core@^1.12.2: + version "1.12.2" + resolved "https://registry.yarnpkg.com/puppeteer-core/-/puppeteer-core-1.12.2.tgz#f4797979aa9fde1045e52b343840f60500d5988e" + integrity sha512-M+atMV5e+MwJdR+OwQVZ1xqAIwh3Ou4nUxNuf334GwpcLG+LDj5BwIph4J9y8YAViByRtWGL+uF8qX2Ggzb+Fg== + dependencies: + debug "^4.1.0" + extract-zip "^1.6.6" + https-proxy-agent "^2.2.1" + mime "^2.0.3" + progress "^2.0.1" + proxy-from-env "^1.0.0" + rimraf "^2.6.1" + ws "^6.1.0" + +readable-stream@^2.2.2: + version "2.3.6" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" + integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +rimraf@^2.6.1: + version "2.6.3" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" + integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== + dependencies: + glob "^7.1.3" + +safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + +typedarray@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" + integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= + +util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= + +ws@^6.1.0: + version "6.1.4" + resolved "https://registry.yarnpkg.com/ws/-/ws-6.1.4.tgz#5b5c8800afab925e94ccb29d153c8d02c1776ef9" + integrity sha512-eqZfL+NE/YQc1/ZynhojeV8q+H050oR8AZ2uIev7RU10svA9ZnJUddHcOUZTJLinZ9yEfdA2kSATS2qZK5fhJA== + dependencies: + async-limiter "~1.0.0" + +yauzl@2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.4.1.tgz#9528f442dab1b2284e58b4379bb194e22e0c4005" + integrity sha1-lSj0QtqxsihOWLQ3m7GU4i4MQAU= + dependencies: + fd-slicer "~1.0.1" diff --git a/now.json b/now.json index 6293c6aba..99829c4c5 100644 --- a/now.json +++ b/now.json @@ -2,12 +2,21 @@ "version": 2, "builds": [ { - "src": "servers/assets/server.js", - "use": "@now/node-server@canary", + "src": "lambdas/chromium/screenshot.js", + "use": "@now/node", "config": { - "maxLambdaSize": "60mb" + "maxLambdaSize": "50mb" } } ], - "routes": [{ "src": "/.*", "dest": "/servers/assets/server.js" }] + "routes": [ + { + "src": "/screenshot", + "dest": "/lambdas/chromium/screenshot.js" + } + ], + "env": { + "URL_WHITELIST": "@url_whitelist", + "DEBUG": "screenshot" + } } diff --git a/packages/assets/README.md b/packages/assets/README.md index 8f7625d7f..3403ccbab 100644 --- a/packages/assets/README.md +++ b/packages/assets/README.md @@ -1,9 +1,14 @@ # @orbiting/backend-modules-assets -This module contains libs to un-/prefix relative asset urls, upload to S3 and most importantly express middlewares for asset proxying and image manipulation (resizing, greyscaling, webp format transformation). It streams assets from other urls, from s3 buckets, out of github repos and can render webpages to PNGs. +This module contains libs to un-/prefix relative asset urls, upload to S3 and most importantly express middlewares for asset proxying and image manipulation (resizing, greyscaling, webp format transformation). It streams assets from other urls, from s3 buckets, out of github repos and can render webpages via external services. + +For rendering it calls [lambdas/chromium](lambdas/chromium) via `CHROMIUM_LAMBDA_URL` or falls back to phatomJSCloud (`PHANTOMJSCLOUD_API_KEY`). Check [assets-backend](https://github.com/orbiting/assets-backend) for a deployable, standalone, express wrapper. +## ENVs +See [servers/assets/.env.example](servers/assets/.env.example) for the required envs. + ## URLs ### Endpoints @@ -26,7 +31,7 @@ Check [assets-backend](https://github.com/orbiting/assets-backend) for a deploya - optional :viewport - succeeds deprecated: `width=:width&height=:height` - default 1200x1 - - optional :fullPage + - optional :fullPage (chromium only) - default true - this api screenshots the full page per default (with scrolling), set `fullPage` to `'false'` or `'0'` to crop to viewport - optional :zoomFactor diff --git a/packages/assets/express/render.js b/packages/assets/express/render.js index ea10a133d..002fe1fa0 100644 --- a/packages/assets/express/render.js +++ b/packages/assets/express/render.js @@ -1,10 +1,9 @@ const { - renderUrl, returnImage, getWidthHeight } = require('../lib') +const screenshot = require('../lib/screenshot') const debug = require('debug')('assets:render') -const streamifier = require('streamifier') const { RENDER_URL_WHITELIST @@ -38,10 +37,14 @@ module.exports = (server) => { height = _height } + if (!url) { + res.status(422) + return res.end('missing url param') + } + const allowed = - url && - whitelistedUrls && - !!whitelistedUrls.find(whiteUrl => url.indexOf(whiteUrl) === 0) + (RENDER_URL_WHITELIST && RENDER_URL_WHITELIST === 'all') || + (whitelistedUrls && !!whitelistedUrls.find(whiteUrl => url.indexOf(whiteUrl) === 0)) if (!allowed) { console.warn('unauthorized render url requested: ' + url) @@ -51,7 +54,7 @@ module.exports = (server) => { let result, error try { - result = await renderUrl(url, width, height, zoomFactor, fullPage) + result = await screenshot({ url, width, height, zoomFactor, fullPage }) } catch (e) { error = e } @@ -68,7 +71,7 @@ module.exports = (server) => { return returnImage({ response: res, - stream: streamifier.createReadStream(result), + stream: result, options: { ...req.query, cacheTags: ['render'] diff --git a/packages/assets/lib/index.js b/packages/assets/lib/index.js index 074b43085..51386b03d 100644 --- a/packages/assets/lib/index.js +++ b/packages/assets/lib/index.js @@ -6,7 +6,6 @@ const returnImage = require('./returnImage') const urlPrefixing = require('./urlPrefixing') const webp = require('./webp') const Repo = require('./Repo') -const renderUrl = require('./renderUrl') module.exports = { upload, @@ -17,6 +16,5 @@ module.exports = { webp, Repo, urlPrefixing, - renderUrl, ...urlPrefixing } diff --git a/packages/assets/lib/renderUrl.js b/packages/assets/lib/renderUrl.js deleted file mode 100644 index cedccbed1..000000000 --- a/packages/assets/lib/renderUrl.js +++ /dev/null @@ -1,74 +0,0 @@ -const puppeteer = require('puppeteer-core') -const chromium = require('chrome-aws-lambda') - -const { - PUPPETEER_WS_ENDPOINT, - FRONTEND_BASIC_AUTH_USER, - FRONTEND_BASIC_AUTH_PASS, - RENDER_COOKIE -} = process.env - -// returns buffer -module.exports = async ( - url, - width, - height, - zoomFactor, - fullPage = true -) => { - let browser - if (chromium.headless) { - console.log('rendering with local headless chrome') - browser = await puppeteer.launch({ - args: chromium.args, - executablePath: await chromium.executablePath, - headless: chromium.headless - }) - } else { - if (!PUPPETEER_WS_ENDPOINT) { - console.warn('missing env PUPPETEER_WS_ENDPOINT, cannot render') - return - } - console.log('rendering with external chrome') - browser = await puppeteer.connect({ - browserWSEndpoint: PUPPETEER_WS_ENDPOINT - }) - } - - const page = await browser.newPage() - - const promises = [ - page.setViewport({ - width: Math.ceil(Math.abs(width)) || 1200, - height: Math.ceil(Math.abs(height)) || 1, - deviceScaleFactor: Math.abs(zoomFactor) || 1 - }), - page.setExtraHTTPHeaders({ 'DNT': '1' }) - ] - - if (RENDER_COOKIE) { - const [name, value] = RENDER_COOKIE.split('=') - promises.push( - page.setCookie({ name, value, url }) - ) - } - - await Promise.all(promises) - - await page.goto(url) - - if (FRONTEND_BASIC_AUTH_USER) { - await page.authenticate({ - username: FRONTEND_BASIC_AUTH_USER, - password: FRONTEND_BASIC_AUTH_PASS - }) - } - - const screenshot = await page.screenshot({ - fullPage: !(['false', '0'].includes(fullPage)) - }) - - browser.close() - - return screenshot -} diff --git a/packages/assets/lib/screenshot/chromium.js b/packages/assets/lib/screenshot/chromium.js new file mode 100644 index 000000000..dced9b2cd --- /dev/null +++ b/packages/assets/lib/screenshot/chromium.js @@ -0,0 +1,32 @@ +const fetch = require('isomorphic-unfetch') + +const { + CHROMIUM_LAMBDA_URL, + RENDER_COOKIE, + BASIC_AUTH_USER, + BASIC_AUTH_PASS +} = process.env + +const canRender = () => + !!CHROMIUM_LAMBDA_URL + +const render = (params) => { + const url = new URL(CHROMIUM_LAMBDA_URL) + for (let key of Object.keys(params)) { + url.searchParams.set(key, params[key]) + } + if (RENDER_COOKIE) { + url.searchParams.set('cookie', RENDER_COOKIE) + } + if (BASIC_AUTH_USER) { + url.searchParams.set('basicAuthUser', BASIC_AUTH_USER) + url.searchParams.set('basicAuthPass', BASIC_AUTH_PASS) + } + return fetch(url.toString()) + .then(result => result.body) +} + +module.exports = { + canRender, + render +} diff --git a/packages/assets/lib/screenshot/index.js b/packages/assets/lib/screenshot/index.js new file mode 100644 index 000000000..daa2e1104 --- /dev/null +++ b/packages/assets/lib/screenshot/index.js @@ -0,0 +1,11 @@ +const phantom = require('./phantom') +const chromium = require('./chromium') + +module.exports = async (params) => { + if (chromium.canRender()) { + return chromium.render(params) + } else if (phantom.canRender()) { + return phantom.render(params) + } + console.error('no renderer available') +} diff --git a/packages/assets/lib/screenshot/phantom.js b/packages/assets/lib/screenshot/phantom.js new file mode 100644 index 000000000..4595fa02f --- /dev/null +++ b/packages/assets/lib/screenshot/phantom.js @@ -0,0 +1,71 @@ +const fetch = require('isomorphic-unfetch') +const { + PHANTOMJSCLOUD_API_KEY, + FRONTEND_BASIC_AUTH_USER, + FRONTEND_BASIC_AUTH_PASS, + PHANTOM_COOKIE +} = process.env + +const canRender = () => + !!PHANTOMJSCLOUD_API_KEY + +const render = ({ + url, + width, + height, + zoomFactor +}) => { + let body = { + url, + content: null, + urlSettings: { + operation: 'GET', + encoding: 'utf8', + headers: {}, + data: null + }, + renderType: 'png', + backend: 'webkit', + outputAsJson: false, + requestSettings: { + ignoreImages: false, + disableJavascript: false, + userAgent: 'Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/534.34 (KHTML, like Gecko) Safari/534.34 PhantomJS/2.0.0 (PhantomJsCloud.com/2.0.1)', + customHeaders: { + 'DNT': 1 + } + }, + renderSettings: {} + } + if (width && height) { + body.renderSettings.viewport = { width, height } + } + if (zoomFactor) { + body.renderSettings.zoomFactor = zoomFactor + } + if (PHANTOM_COOKIE) { + body.requestSettings.customHeaders = { + 'cookie': PHANTOM_COOKIE + } + } + if (FRONTEND_BASIC_AUTH_USER) { + body.requestSettings.authentication = { + userName: FRONTEND_BASIC_AUTH_USER, + password: FRONTEND_BASIC_AUTH_PASS + } + } + + return fetch(`https://PhantomJsCloud.com/api/browser/v2/${PHANTOMJSCLOUD_API_KEY}/`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify(body) + }) + .then(result => result.body) +} + +module.exports = { + canRender, + render +} diff --git a/packages/assets/package.json b/packages/assets/package.json index 61898e92c..17d918654 100644 --- a/packages/assets/package.json +++ b/packages/assets/package.json @@ -26,14 +26,11 @@ "aws-sdk": "^2.246.1", "bluebird": "^3.5.1", "check-env": "^1.3.0", - "chrome-aws-lambda": "^1.11.2", "debug": "^3.1.0", "export-files": "^2.1.1", "file-type-stream": "^1.0.0", - "puppeteer-core": "^1.12.2", "sharp": "^0.20.1", - "stream-to-array": "^2.3.0", - "streamifier": "^0.1.1" + "stream-to-array": "^2.3.0" }, "peerDependencies": { "isomorphic-unfetch": "^2.0.0" diff --git a/servers/assets/.env.example b/servers/assets/.env.example index a094fe8e0..1b0d10281 100644 --- a/servers/assets/.env.example +++ b/servers/assets/.env.example @@ -11,7 +11,7 @@ PORT=5020 # optional: #BASIC_AUTH_REALM= -# send basic auth to frontend (for /render and /frontend, leaks to phantomjscloud) +# phantom only: send basic auth to frontend (for /render and /frontend, leaks to phantomjscloud) #FRONTEND_BASIC_AUTH_USER= #FRONTEND_BASIC_AUTH_PASS= @@ -32,16 +32,24 @@ PORT=5020 # render ############# -# the chrome for puppeteer to connect to -# required for the /render endpoint to work -#PUPPETEER_WS_ENDPOINT= +# url of lambda/chromium deployment +#CHROMIUM_LAMBDA_URL=https://republik-screenshot.now.sh/screenshot +# alternativly render with phantomJSCloud +#PHANTOMJSCLOUD_API_KEY= # render urls must start with the following prefix #RENDER_URL_WHITELIST=https://www.republik.ch +# provide all allow any url +RENDER_URL_WHITELIST=all -# set a cookie in chromes page +# optional: set a cookie in chromes page #RENDER_COOKIE= +# optional: send basic auth when rendering urls +#BASIC_AUTH_USER= +#BASIC_AUTH_PASS= + + ############# # embeds ############# diff --git a/servers/assets/README.md b/servers/assets/README.md index 160ce0f8a..0ecf030a9 100644 --- a/servers/assets/README.md +++ b/servers/assets/README.md @@ -1,7 +1,7 @@ Assets Backend --------------- -This is a lightweight, fast nodejs-express server for asset proxying and image manipulation (resizing, greyscaling, webp format transformation). It streams assets from other urls, from s3 buckets, out of github repos and can render webpages to PNGs. +This is a lightweight, fast nodejs-express server for asset proxying and image manipulation (resizing, greyscaling, webp format transformation). It streams assets from other urls, from s3 buckets, out of github repos and can render via external serves. Check the [README](https://github.com/orbiting/backends/tree/master/packages/assets/README.md) of [backend-modules-assets](https://github.com/orbiting/backends/tree/master/packages/assets) which contains all the relevant code. @@ -15,22 +15,16 @@ TODO: system diagram ### Quick start You need to have node (8.3.0+) installed and postgres running somewhere. -Boostrap your .env file (see [.env.example](.env.example)). +Boostrap your .env file (copy [.env.example](.env.example)). Also see [backend-modules-assets README](https://github.com/orbiting/backends/tree/master/packages/assets/README.md) -``` -PORT=3021 -PUBLIC_URL=http://localhost:3021 +The following ENVs have a dependency to other servers: +``` # must be in sync with PUBLIC_URL ASSETS_SERVER_BASE_URL=http://localhost:3021 # must be in sync with republik-backend and publikator-backend ASSETS_HMAC_KEY=aiy3sheYoobahb4eth1ohs4aoPaezeeg -# endpoint for puppeteer to render overview-teasers, social media share images, etc -PUPPETEER_WS_ENDPOINT= -# list urls allowed on the /render endpoint, the beginning must match -RENDER_URL_WHITELIST=https://www.republik.ch/ - # GITHUB auth server images from github repos # Follow the "Auth - Github" section of republik-backend to get these GITHUB_LOGIN= diff --git a/yarn.lock b/yarn.lock index f3638c0a2..86c0d28ea 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1693,11 +1693,6 @@ chownr@^1.0.1: resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.0.1.tgz#e2a75042a9551908bebd25b8523d5f9769d79181" integrity sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE= -chrome-aws-lambda@^1.11.2: - version "1.11.2" - resolved "https://registry.yarnpkg.com/chrome-aws-lambda/-/chrome-aws-lambda-1.11.2.tgz#5cf7ed4f90157007f78a8e30a79df89ac2c48906" - integrity sha512-BpR7qYNkPZlMQGZI3/edrPT4Rx9Hd/Z+YV3dQ5ujfWj01r27pYYOoOmMd2w3mkmFeHF7nzFlksM/urKnfICwDQ== - ci-info@^1.0.0: version "1.1.3" resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.1.3.tgz#710193264bb05c77b8c90d02f5aaf22216a667b2" @@ -1965,7 +1960,7 @@ concat-map@0.0.1: resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= -concat-stream@1.6.2, concat-stream@^1.4.7, concat-stream@^1.5.0, concat-stream@^1.6.0: +concat-stream@^1.4.7, concat-stream@^1.5.0, concat-stream@^1.6.0: version "1.6.2" resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== @@ -2609,13 +2604,6 @@ debug@3.1.0, debug@^3.1.0: dependencies: ms "2.0.0" -debug@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" - integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== - dependencies: - ms "^2.1.1" - decamelize@^1.0.0, decamelize@^1.1.1, decamelize@^1.1.2: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" @@ -3510,16 +3498,6 @@ extglob@^2.0.4: snapdragon "^0.8.1" to-regex "^3.0.1" -extract-zip@^1.6.6: - version "1.6.7" - resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-1.6.7.tgz#a840b4b8af6403264c8db57f4f1a74333ef81fe9" - integrity sha1-qEC0uK9kAyZMjbV/Txp0Mz74H+k= - dependencies: - concat-stream "1.6.2" - debug "2.6.9" - mkdirp "0.5.1" - yauzl "2.4.1" - extsprintf@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" @@ -3589,13 +3567,6 @@ fbjs@^0.8.12, fbjs@^0.8.16: setimmediate "^1.0.5" ua-parser-js "^0.7.9" -fd-slicer@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.0.1.tgz#8b5bcbd9ec327c5041bf9ab023fd6750f1177e65" - integrity sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU= - dependencies: - pend "~1.2.0" - figures@^1.3.5, figures@^1.4.0, figures@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e" @@ -4634,7 +4605,7 @@ http-signature@~1.2.0: version "3.3.6" resolved "https://github.com/node-apn/node-http2/archive/apn-2.1.4.tar.gz#8333dee2d6e0089152cefad30f41ced502f9c366" -https-proxy-agent@^2.2.0, https-proxy-agent@^2.2.1: +https-proxy-agent@^2.2.0: version "2.2.1" resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz#51552970fa04d723e04c56d04178c3f92592bbc0" integrity sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ== @@ -6458,11 +6429,6 @@ mime@1.4.1: resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6" integrity sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ== -mime@^2.0.3: - version "2.4.0" - resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.0.tgz#e051fd881358585f3279df333fe694da0bcffdd6" - integrity sha512-ikBcWwyqXQSHKtciCcctu9YfPbFYZ4+gbHEmE0Q8jzcTYQg5dHCr3g2wwAZjPoJfQVXZq6KXAjpXOTf5/cjT7w== - mime@^2.2.0: version "2.3.1" resolved "https://registry.yarnpkg.com/mime/-/mime-2.3.1.tgz#b1621c54d63b97c47d3cfe7f7215f7d64517c369" @@ -6541,7 +6507,7 @@ mixin-deep@^1.2.0: for-in "^1.0.2" is-extendable "^1.0.1" -mkdirp@0.5.1, mkdirp@0.5.x, mkdirp@0.x.x, mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0: +mkdirp@0.5.x, mkdirp@0.x.x, mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0: version "0.5.1" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= @@ -7396,11 +7362,6 @@ pause@0.0.1: resolved "https://registry.yarnpkg.com/pause/-/pause-0.0.1.tgz#1d408b3fdb76923b9543d96fb4c9dfd535d9cb5d" integrity sha1-HUCLP9t2kjuVQ9lvtMnf1TXZy10= -pend@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" - integrity sha1-elfrVQpng/kRUzH89GY9XI4AelA= - performance-now@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" @@ -7822,11 +7783,6 @@ progress@^2.0.0: resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.0.tgz#8a1be366bf8fc23db2bd23f10c6fe920b4389d1f" integrity sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8= -progress@^2.0.1: - version "2.0.3" - resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" - integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== - promise-chains@^0.3.11: version "0.3.12" resolved "https://registry.yarnpkg.com/promise-chains/-/promise-chains-0.3.12.tgz#68e63484c9b962f1d6e2ab672324d14f5909ee21" @@ -7904,11 +7860,6 @@ proxy-addr@~2.0.3: forwarded "~0.1.2" ipaddr.js "1.6.0" -proxy-from-env@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.0.0.tgz#33c50398f70ea7eb96d21f7b817630a55791c7ee" - integrity sha1-M8UDmPcOp+uW0h97gXYwpVeRx+4= - ps-tree@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/ps-tree/-/ps-tree-1.1.0.tgz#b421b24140d6203f1ed3c76996b4427b08e8c014" @@ -7973,20 +7924,6 @@ punycode@^2.1.0: resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.0.tgz#5f863edc89b96db09074bad7947bf09056ca4e7d" integrity sha1-X4Y+3Im5bbCQdLrXlHvwkFbKTn0= -puppeteer-core@^1.12.2: - version "1.12.2" - resolved "https://registry.yarnpkg.com/puppeteer-core/-/puppeteer-core-1.12.2.tgz#f4797979aa9fde1045e52b343840f60500d5988e" - integrity sha512-M+atMV5e+MwJdR+OwQVZ1xqAIwh3Ou4nUxNuf334GwpcLG+LDj5BwIph4J9y8YAViByRtWGL+uF8qX2Ggzb+Fg== - dependencies: - debug "^4.1.0" - extract-zip "^1.6.6" - https-proxy-agent "^2.2.1" - mime "^2.0.3" - progress "^2.0.1" - proxy-from-env "^1.0.0" - rimraf "^2.6.1" - ws "^6.1.0" - q@2.0.x: version "2.0.3" resolved "https://registry.yarnpkg.com/q/-/q-2.0.3.tgz#75b8db0255a1a5af82f58c3f3aaa1efec7d0d134" @@ -9247,11 +9184,6 @@ stream-to-array@^2.3.0: dependencies: any-promise "^1.1.0" -streamifier@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/streamifier/-/streamifier-0.1.1.tgz#97e98d8fa4d105d62a2691d1dc07e820db8dfc4f" - integrity sha1-l+mNj6TRBdYqJpHR3AfoINuN/E8= - streamsearch@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-0.1.2.tgz#808b9d0e56fc273d809ba57338e929919a1a9f1a" @@ -10379,13 +10311,6 @@ ws@^5.2.0: dependencies: async-limiter "~1.0.0" -ws@^6.1.0: - version "6.1.4" - resolved "https://registry.yarnpkg.com/ws/-/ws-6.1.4.tgz#5b5c8800afab925e94ccb29d153c8d02c1776ef9" - integrity sha512-eqZfL+NE/YQc1/ZynhojeV8q+H050oR8AZ2uIev7RU10svA9ZnJUddHcOUZTJLinZ9yEfdA2kSATS2qZK5fhJA== - dependencies: - async-limiter "~1.0.0" - x-is-string@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/x-is-string/-/x-is-string-0.1.0.tgz#474b50865af3a49a9c4657f05acd145458f77d82" @@ -10507,13 +10432,6 @@ yargs@~3.10.0: decamelize "^1.0.0" window-size "0.1.0" -yauzl@2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.4.1.tgz#9528f442dab1b2284e58b4379bb194e22e0c4005" - integrity sha1-lSj0QtqxsihOWLQ3m7GU4i4MQAU= - dependencies: - fd-slicer "~1.0.1" - zen-observable-ts@^0.8.6: version "0.8.9" resolved "https://registry.yarnpkg.com/zen-observable-ts/-/zen-observable-ts-0.8.9.tgz#d3c97af08c0afdca37ebcadf7cc3ee96bda9bab1"