/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
- 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:
- name: Restart nginx
become: yes

View file

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

View file

@ -22,6 +22,8 @@ const beeline = require("honeycomb-beeline")({
disableInstrumentationOnLoad: true,
});
const playwright = require("playwright");
// To render the image, we load the /internal/assetImage page in the web app,
// a simple page specifically designed for this API endpoint!
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"
: "https://impress-2020.openneo.net/internal/assetImage";
// TODO: We used to share a browser instamce, but we couldn't get it to reload
// correctly after accidental closes, so we're just gonna always load a
// new one now. What are the perf implications of this? Does it slow down
// response time substantially?
async function getBrowser() {
if (process.env["NODE_ENV"] === "production") {
// In production, we use a special chrome-aws-lambda Chromium.
const chromium = require("chrome-aws-lambda");
const playwright = require("playwright-core");
return await playwright.chromium.launch({
args: chromium.args,
executablePath: await chromium.executablePath,
headless: true,
});
} else {
// In development, we use the standard playwright Chromium.
const playwright = require("playwright");
return await playwright.chromium.launch({ headless: true });
// We share one browser instance, but create a new independent "context" for
// each request, as a security hedge. (The intent is for the user to request
// very little from the browser, so it shouldn't matter, but it's just an extra
// layer to reduce the risk of what an attack could do!)
//
// TODO: We're probably going to need to limit the number of concurrent browser
// sessions here, right? I don't actually know how the Next.js server
// handles concurrency though, let's pressure-test and find out before
// building a solution.
let SHARED_BROWSER = null;
async function getBrowserContext() {
if (SHARED_BROWSER == null) {
SHARED_BROWSER = await playwright.chromium.launch({ headless: true });
}
return await SHARED_BROWSER.newContext();
}
async function handle(req, res) {
@ -93,8 +91,8 @@ async function loadAndScreenshotImage(libraryUrl, size) {
}).toString();
console.debug("Opening browser page");
const browser = await getBrowser();
const page = await browser.newPage();
const context = await getBrowserContext();
const page = await context.newPage();
console.debug("Page opened, navigating to: " + assetImagePageUrl.toString());
try {
@ -130,7 +128,7 @@ async function loadAndScreenshotImage(libraryUrl, size) {
console.warn("Error closing page after image finished", e);
}
try {
await browser.close();
await context.close();
} catch (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:
es6-promisify "^5.0.0"
agent-base@6:
agent-base@6, agent-base@^6.0.2:
version "6.0.2"
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77"
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"
integrity sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==
commander@^6.1.0, commander@^6.2.0:
commander@^6.2.0:
version "6.2.1"
resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.1.tgz#0792eb682dfbc325999bb2b84fddddba110ac73c"
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:
version "1.8.0"
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"
integrity sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==
playwright-core@^1.14.0:
version "1.14.0"
resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.14.0.tgz#af51da7b201c11eeda780e2db3f05c8bca74c8be"
integrity sha512-n6NdknezSfRgB6LkLwcrbm5orRQZSpbd8LZmlc4YrIXV0VEvJr5tzP3xlHXpiFBfTr3yoFuagldI3T7bD/8H3w==
playwright-core@=1.16.3:
version "1.16.3"
resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.16.3.tgz#f466be9acaffb698654adfb0a17a4906ba936895"
integrity sha512-16hF27IvQheJee+DbhC941AUZLjbJgfZFWi9YPS4LKEk/lKFhZI+9TiFD0sboYqb9eaEWvul47uR5xxTVbE4iw==
dependencies:
commander "^6.1.0"
commander "^8.2.0"
debug "^4.1.1"
extract-zip "^2.0.1"
https-proxy-agent "^5.0.0"
@ -9691,29 +9696,18 @@ playwright-core@^1.14.0:
proper-lockfile "^4.1.1"
proxy-from-env "^1.1.0"
rimraf "^3.0.2"
socks-proxy-agent "^6.1.0"
stack-utils "^2.0.3"
ws "^7.4.6"
yauzl "^2.10.0"
yazl "^2.5.1"
playwright@^1.14.0:
version "1.14.0"
resolved "https://registry.yarnpkg.com/playwright/-/playwright-1.14.0.tgz#18301b11f5278a446d36b5cf96f67db36ce2cd20"
integrity sha512-aR5oZ1iVsjQkGfYCjgYAmyMAVu0MQ0i8MgdnfdqDu9EVLfbnpuuFmTv/Rb7/Yjno1kOrDUP9+RyNC+zfG3wozA==
playwright@^1.16.3:
version "1.16.3"
resolved "https://registry.yarnpkg.com/playwright/-/playwright-1.16.3.tgz#27a292d9fa54fbac923998d3af58cd2b691f5ebe"
integrity sha512-nfJx/OpIb/8OexL3rYGxNN687hGyaM3XNpfuMzoPlrekURItyuiHHsNhC9oQCx3JDmCn5O3EyyyFCnrZjH6MpA==
dependencies:
commander "^6.1.0"
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"
playwright-core "=1.16.3"
please-upgrade-node@^3.2.0:
version "3.2.0"
@ -10928,6 +10922,23 @@ socks-proxy-agent@^4.0.1:
agent-base "~4.2.1"
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:
version "2.3.3"
resolved "https://registry.yarnpkg.com/socks/-/socks-2.3.3.tgz#01129f0a5d534d2b897712ed8aceab7ee65d78e3"