/api/assetImage fixes in production

Now that we're not on Vercel's AWS Lambda deployment, we can switch to something a bit more standard!

I also tweaked up our version of Playwright, because, hey, why not?

Getting the package list was a bit tricky, but we got there! Left a comment to explain where it's from.
This commit is contained in:
Emi Matchu 2021-11-12 21:20:48 -08:00
parent 5470a49651
commit 9753cbe173
4 changed files with 105 additions and 48 deletions

View file

@ -267,6 +267,55 @@
- libgif-dev - libgif-dev
- librsvg2-dev - librsvg2-dev
- name: Install Playwright system dependencies
# NOTE: I copied the package list from the source list for
# `npx playwright install-deps`, which I couldn't get running in
# Ansible as root, and besides, I prefer manually managing the
# package list over running an npm script as root!
become: yes
apt:
update_cache: yes
name:
# Tools
- xvfb
- fonts-noto-color-emoji
- ttf-unifont
- libfontconfig
- libfreetype6
- xfonts-cyrillic
- xfonts-scalable
- fonts-liberation
- fonts-ipafont-gothic
- fonts-wqy-zenhei
- fonts-tlwg-loma-otf
- ttf-ubuntu-font-family
# Chromium
- fonts-liberation
- libasound2
- libatk-bridge2.0-0
- libatk1.0-0
- libatspi2.0-0
- libcairo2
- libcups2
- libdbus-1-3
- libdrm2
- libegl1
- libgbm1
- libglib2.0-0
- libgtk-3-0
- libnspr4
- libnss3
- libpango-1.0-0
- libx11-6
- libx11-xcb1
- libxcb1
- libxcomposite1
- libxdamage1
- libxext6
- libxfixes3
- libxrandr2
- libxshmfence1
handlers: handlers:
- name: Restart nginx - name: Restart nginx
become: yes become: yes

View file

@ -43,7 +43,7 @@
"mysql2": "^2.1.0", "mysql2": "^2.1.0",
"next": "12.0.2", "next": "12.0.2",
"node-fetch": "^2.6.0", "node-fetch": "^2.6.0",
"playwright-core": "^1.14.0", "playwright": "^1.16.3",
"react": "^17.0.1", "react": "^17.0.1",
"react-autosuggest": "^10.0.2", "react-autosuggest": "^10.0.2",
"react-dom": "^17.0.1", "react-dom": "^17.0.1",
@ -112,7 +112,6 @@
"inquirer": "^7.3.3", "inquirer": "^7.3.3",
"jest-image-snapshot": "^4.3.0", "jest-image-snapshot": "^4.3.0",
"lint-staged": "^10.5.4", "lint-staged": "^10.5.4",
"playwright": "^1.14.0",
"prettier": "^2.0.5", "prettier": "^2.0.5",
"react-is": "^16.13.1", "react-is": "^16.13.1",
"ts-node": "^9.1.1", "ts-node": "^9.1.1",

View file

@ -22,6 +22,8 @@ const beeline = require("honeycomb-beeline")({
disableInstrumentationOnLoad: true, disableInstrumentationOnLoad: true,
}); });
const playwright = require("playwright");
// To render the image, we load the /internal/assetImage page in the web app, // To render the image, we load the /internal/assetImage page in the web app,
// a simple page specifically designed for this API endpoint! // a simple page specifically designed for this API endpoint!
const ASSET_IMAGE_PAGE_BASE_URL = process.env.VERCEL_URL const ASSET_IMAGE_PAGE_BASE_URL = process.env.VERCEL_URL
@ -30,25 +32,21 @@ const ASSET_IMAGE_PAGE_BASE_URL = process.env.VERCEL_URL
? "http://localhost:3000/internal/assetImage" ? "http://localhost:3000/internal/assetImage"
: "https://impress-2020.openneo.net/internal/assetImage"; : "https://impress-2020.openneo.net/internal/assetImage";
// TODO: We used to share a browser instamce, but we couldn't get it to reload // We share one browser instance, but create a new independent "context" for
// correctly after accidental closes, so we're just gonna always load a // each request, as a security hedge. (The intent is for the user to request
// new one now. What are the perf implications of this? Does it slow down // very little from the browser, so it shouldn't matter, but it's just an extra
// response time substantially? // layer to reduce the risk of what an attack could do!)
async function getBrowser() { //
if (process.env["NODE_ENV"] === "production") { // TODO: We're probably going to need to limit the number of concurrent browser
// In production, we use a special chrome-aws-lambda Chromium. // sessions here, right? I don't actually know how the Next.js server
const chromium = require("chrome-aws-lambda"); // handles concurrency though, let's pressure-test and find out before
const playwright = require("playwright-core"); // building a solution.
return await playwright.chromium.launch({ let SHARED_BROWSER = null;
args: chromium.args, async function getBrowserContext() {
executablePath: await chromium.executablePath, if (SHARED_BROWSER == null) {
headless: true, SHARED_BROWSER = await playwright.chromium.launch({ headless: true });
});
} else {
// In development, we use the standard playwright Chromium.
const playwright = require("playwright");
return await playwright.chromium.launch({ headless: true });
} }
return await SHARED_BROWSER.newContext();
} }
async function handle(req, res) { async function handle(req, res) {
@ -93,8 +91,8 @@ async function loadAndScreenshotImage(libraryUrl, size) {
}).toString(); }).toString();
console.debug("Opening browser page"); console.debug("Opening browser page");
const browser = await getBrowser(); const context = await getBrowserContext();
const page = await browser.newPage(); const page = await context.newPage();
console.debug("Page opened, navigating to: " + assetImagePageUrl.toString()); console.debug("Page opened, navigating to: " + assetImagePageUrl.toString());
try { try {
@ -130,7 +128,7 @@ async function loadAndScreenshotImage(libraryUrl, size) {
console.warn("Error closing page after image finished", e); console.warn("Error closing page after image finished", e);
} }
try { try {
await browser.close(); await context.close();
} catch (e) { } catch (e) {
console.warn("Error closing browser after image finished", e); console.warn("Error closing browser after image finished", e);
} }

View file

@ -3523,7 +3523,7 @@ agent-base@4, agent-base@^4.2.0, agent-base@^4.3.0:
dependencies: dependencies:
es6-promisify "^5.0.0" es6-promisify "^5.0.0"
agent-base@6: agent-base@6, agent-base@^6.0.2:
version "6.0.2" version "6.0.2"
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77"
integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==
@ -4961,11 +4961,16 @@ commander@^5.1.0:
resolved "https://registry.yarnpkg.com/commander/-/commander-5.1.0.tgz#46abbd1652f8e059bddaef99bbdcb2ad9cf179ae" resolved "https://registry.yarnpkg.com/commander/-/commander-5.1.0.tgz#46abbd1652f8e059bddaef99bbdcb2ad9cf179ae"
integrity sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg== integrity sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==
commander@^6.1.0, commander@^6.2.0: commander@^6.2.0:
version "6.2.1" version "6.2.1"
resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.1.tgz#0792eb682dfbc325999bb2b84fddddba110ac73c" resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.1.tgz#0792eb682dfbc325999bb2b84fddddba110ac73c"
integrity sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA== integrity sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==
commander@^8.2.0:
version "8.3.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66"
integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==
common-tags@^1.8.0: common-tags@^1.8.0:
version "1.8.0" version "1.8.0"
resolved "https://registry.yarnpkg.com/common-tags/-/common-tags-1.8.0.tgz#8e3153e542d4a39e9b10554434afaaf98956a937" resolved "https://registry.yarnpkg.com/common-tags/-/common-tags-1.8.0.tgz#8e3153e542d4a39e9b10554434afaaf98956a937"
@ -9675,12 +9680,12 @@ platform@1.3.6:
resolved "https://registry.yarnpkg.com/platform/-/platform-1.3.6.tgz#48b4ce983164b209c2d45a107adb31f473a6e7a7" resolved "https://registry.yarnpkg.com/platform/-/platform-1.3.6.tgz#48b4ce983164b209c2d45a107adb31f473a6e7a7"
integrity sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg== integrity sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==
playwright-core@^1.14.0: playwright-core@=1.16.3:
version "1.14.0" version "1.16.3"
resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.14.0.tgz#af51da7b201c11eeda780e2db3f05c8bca74c8be" resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.16.3.tgz#f466be9acaffb698654adfb0a17a4906ba936895"
integrity sha512-n6NdknezSfRgB6LkLwcrbm5orRQZSpbd8LZmlc4YrIXV0VEvJr5tzP3xlHXpiFBfTr3yoFuagldI3T7bD/8H3w== integrity sha512-16hF27IvQheJee+DbhC941AUZLjbJgfZFWi9YPS4LKEk/lKFhZI+9TiFD0sboYqb9eaEWvul47uR5xxTVbE4iw==
dependencies: dependencies:
commander "^6.1.0" commander "^8.2.0"
debug "^4.1.1" debug "^4.1.1"
extract-zip "^2.0.1" extract-zip "^2.0.1"
https-proxy-agent "^5.0.0" https-proxy-agent "^5.0.0"
@ -9691,29 +9696,18 @@ playwright-core@^1.14.0:
proper-lockfile "^4.1.1" proper-lockfile "^4.1.1"
proxy-from-env "^1.1.0" proxy-from-env "^1.1.0"
rimraf "^3.0.2" rimraf "^3.0.2"
socks-proxy-agent "^6.1.0"
stack-utils "^2.0.3" stack-utils "^2.0.3"
ws "^7.4.6" ws "^7.4.6"
yauzl "^2.10.0"
yazl "^2.5.1" yazl "^2.5.1"
playwright@^1.14.0: playwright@^1.16.3:
version "1.14.0" version "1.16.3"
resolved "https://registry.yarnpkg.com/playwright/-/playwright-1.14.0.tgz#18301b11f5278a446d36b5cf96f67db36ce2cd20" resolved "https://registry.yarnpkg.com/playwright/-/playwright-1.16.3.tgz#27a292d9fa54fbac923998d3af58cd2b691f5ebe"
integrity sha512-aR5oZ1iVsjQkGfYCjgYAmyMAVu0MQ0i8MgdnfdqDu9EVLfbnpuuFmTv/Rb7/Yjno1kOrDUP9+RyNC+zfG3wozA== integrity sha512-nfJx/OpIb/8OexL3rYGxNN687hGyaM3XNpfuMzoPlrekURItyuiHHsNhC9oQCx3JDmCn5O3EyyyFCnrZjH6MpA==
dependencies: dependencies:
commander "^6.1.0" playwright-core "=1.16.3"
debug "^4.1.1"
extract-zip "^2.0.1"
https-proxy-agent "^5.0.0"
jpeg-js "^0.4.2"
mime "^2.4.6"
pngjs "^5.0.0"
progress "^2.0.3"
proper-lockfile "^4.1.1"
proxy-from-env "^1.1.0"
rimraf "^3.0.2"
stack-utils "^2.0.3"
ws "^7.4.6"
yazl "^2.5.1"
please-upgrade-node@^3.2.0: please-upgrade-node@^3.2.0:
version "3.2.0" version "3.2.0"
@ -10928,6 +10922,23 @@ socks-proxy-agent@^4.0.1:
agent-base "~4.2.1" agent-base "~4.2.1"
socks "~2.3.2" socks "~2.3.2"
socks-proxy-agent@^6.1.0:
version "6.1.0"
resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-6.1.0.tgz#869cf2d7bd10fea96c7ad3111e81726855e285c3"
integrity sha512-57e7lwCN4Tzt3mXz25VxOErJKXlPfXmkMLnk310v/jwW20jWRVcgsOit+xNkN3eIEdB47GwnfAEBLacZ/wVIKg==
dependencies:
agent-base "^6.0.2"
debug "^4.3.1"
socks "^2.6.1"
socks@^2.6.1:
version "2.6.1"
resolved "https://registry.yarnpkg.com/socks/-/socks-2.6.1.tgz#989e6534a07cf337deb1b1c94aaa44296520d30e"
integrity sha512-kLQ9N5ucj8uIcxrDwjm0Jsqk06xdpBjGNQtpXy4Q8/QY2k+fY7nZH8CARy+hkbG+SGAovmzzuauCpBlb8FrnBA==
dependencies:
ip "^1.1.5"
smart-buffer "^4.1.0"
socks@~2.3.2: socks@~2.3.2:
version "2.3.3" version "2.3.3"
resolved "https://registry.yarnpkg.com/socks/-/socks-2.3.3.tgz#01129f0a5d534d2b897712ed8aceab7ee65d78e3" resolved "https://registry.yarnpkg.com/socks/-/socks-2.3.3.tgz#01129f0a5d534d2b897712ed8aceab7ee65d78e3"