UNPKG

webstack-screenshot

Version:

📸网站截图 API | Website Screenshot API

233 lines (223 loc) • 7.9 kB
'use strict'; const screenshot = require('./shared/webstack-screenshot.C_kd1VBn.cjs'); const node_buffer = require('node:buffer'); const puppeteer$1 = require('puppeteer-core'); const process = require('node:process'); const sparticuzPuppeteer = require('@sparticuz/chromium'); const puppeteer = require('puppeteer'); const http = require('node:http'); const bodyData = require('body-data'); function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; } const puppeteer__default$1 = /*#__PURE__*/_interopDefaultCompat(puppeteer$1); const process__default = /*#__PURE__*/_interopDefaultCompat(process); const sparticuzPuppeteer__default = /*#__PURE__*/_interopDefaultCompat(sparticuzPuppeteer); const puppeteer__default = /*#__PURE__*/_interopDefaultCompat(puppeteer); const http__default = /*#__PURE__*/_interopDefaultCompat(http); const args = (() => { const puppeteerFlags = [ "--allow-pre-commit-input", "--disable-background-networking", "--disable-background-timer-throttling", "--disable-backgrounding-occluded-windows", "--disable-breakpad", "--disable-client-side-phishing-detection", "--disable-component-extensions-with-background-pages", "--disable-component-update", "--disable-default-apps", "--disable-dev-shm-usage", "--disable-extensions", "--disable-hang-monitor", "--disable-ipc-flooding-protection", "--disable-popup-blocking", "--disable-prompt-on-repost", "--disable-renderer-backgrounding", "--disable-sync", "--enable-automation", // TODO(sadym): remove '--enable-blink-features=IdleDetection' once // IdleDetection is turned on by default. "--enable-blink-features=IdleDetection", "--export-tagged-pdf", "--force-color-profile=srgb", "--metrics-recording-only", "--no-first-run", "--password-store=basic", "--use-mock-keychain" ]; const puppeteerDisableFeatures = [ "Translate", "BackForwardCache", // AcceptCHFrame disabled because of crbug.com/1348106. "AcceptCHFrame", "MediaRouter", "OptimizationHints" ]; const puppeteerEnableFeatures = ["NetworkServiceInProcess2"]; const chromiumFlags = [ "--disable-domain-reliability", "--disable-print-preview", "--disable-speech-api", "--disk-cache-size=33554432", "--mute-audio", "--no-default-browser-check", "--no-pings", // Needs to be single-process to avoid `prctl(PR_SET_NO_NEW_PRIVS) failed` error "--single-process" ]; const chromiumDisableFeatures = ["AudioServiceOutOfProcess", "IsolateOrigins", "site-per-process"]; const chromiumEnableFeatures = ["SharedArrayBuffer"]; const graphicsFlags = [ "--hide-scrollbars", "--ignore-gpu-blocklist", "--in-process-gpu", // https://chromium.googlesource.com/chromium/src/+/main/docs/gpu/swiftshader.md "--use-gl=angle", "--use-angle=swiftshader", // https://source.chromium.org/search?q=lang:cpp+symbol:kWindowSize&ss=chromium "--window-size=1920,1080" ]; const insecureFlags = [ "--allow-running-insecure-content", "--disable-setuid-sandbox", "--disable-site-isolation-trials", "--disable-web-security", "--no-sandbox", // https://source.chromium.org/search?q=lang:cpp+symbol:kNoZygote&ss=chromium "--no-zygote" ]; return [ ...puppeteerFlags, ...chromiumFlags, `--disable-features=${[...puppeteerDisableFeatures, ...chromiumDisableFeatures].join(",")}`, `--enable-features=${[...puppeteerEnableFeatures, ...chromiumEnableFeatures].join(",")}`, ...graphicsFlags, ...insecureFlags, "--headless='new'" ]; })(); const { WEBSTACK_SCREENSHOT_PUPPETEER_EXECUTABLE_PATH, WEBSTACK_SCREENSHOT_IS_AWS_LAMBDA, WEBSTACK_SCREENSHOT_FONTS } = process__default.env; function isNumber(value) { return !Number.isNaN(value); } function isHttp(url) { return /^https?:\/\//.test(url); } async function getLaunch(options = {}) { const opts = { ...options, headless: "shell", executablePath: puppeteer__default.executablePath() }; if (WEBSTACK_SCREENSHOT_IS_AWS_LAMBDA) { if (WEBSTACK_SCREENSHOT_FONTS) { const fonts = WEBSTACK_SCREENSHOT_FONTS.split(",").filter(Boolean).map((font) => sparticuzPuppeteer__default.font(font)); await Promise.all(fonts); } opts.args = sparticuzPuppeteer__default.args; opts.executablePath = await sparticuzPuppeteer__default.executablePath(); } if (WEBSTACK_SCREENSHOT_PUPPETEER_EXECUTABLE_PATH) { opts.executablePath = WEBSTACK_SCREENSHOT_PUPPETEER_EXECUTABLE_PATH; } return opts; } function cache(cache2) { if (cache2 === false || cache2 === 0) { return void 0; } const sec = Math.abs(cache2); const daySec = 86400; const cacheKey = "public, no-transform, s-maxage=$, max-age=$"; if (!cache2) { return cacheKey.replace(/\$/g, daySec.toString()); } if (isNumber(sec)) { return cacheKey.replace(/\$/g, sec.toString()); } return void 0; } let browser, page; async function getScreenshot(data) { try { data.url = isHttp(data.url) ? data.url : `http://${data.url}`; if (!browser) { const launchOpt = await getLaunch({}); browser = await puppeteer__default$1.launch(launchOpt); } const screenshot$1 = screenshot.Screenshot.getInstance(); page = await browser.newPage(); const buffer = await screenshot$1.getScreenshot(page, data); await new Promise((r) => setTimeout(r, (data.await || 0) + 1e3)); return buffer; } catch (error) { console.error(error); if (browser) { browser.close(); browser = null; } } finally { if (page) { await page.close(); page = null; } } return node_buffer.Buffer.from(""); } async function serverless(req, res) { console.log("NODE.js", process__default.version); if (req.url === "/favicon.ico") { res.end(); return; } res.setHeader("Access-Control-Allow-Origin", "*"); res.setHeader("Content-Type", "application/json; charset=utf-8"); try { const { params, body } = await bodyData.bodyData(req); const data = req.method?.toUpperCase() === "POST" ? body : params; if (!data.url) { const projectUrl = "https://github.com/Lete114/WebStack-Screenshot#properties"; const msg = { msg: `URL not detected , Using parameters: ${projectUrl}` }; res.end(JSON.stringify(msg)); return; } if (!isHttp(data.url)) { const msg = { msg: "URL must start with http:// or https://" }; res.end(JSON.stringify(msg)); return; } const content = await getScreenshot(data); const cacheResult = cache(data.cache); if (cacheResult) { res.setHeader("Cache-Control", cacheResult); } const instance = screenshot.Screenshot.getInstance(); const options = instance.parse(data); if (options.encoding === "base64") { const base64 = `data:image/${options.type};base64,${content}`; res.end(JSON.stringify({ data: base64 })); } else { res.setHeader("Content-Type", `image/${options.type}`); res.write(content, options.encoding); } res.end(); } catch (error) { console.error(error); res.end(JSON.stringify({ msg: "Screenshot failed" })); } } const PORT = process__default.env.WEBSTACK_SCREENSHOT_PORT || process__default.env.PORT || 6870; function startServer(port = PORT) { const server = http__default.createServer(serverless); server.listen(port, () => { console.log(`Service is up and running port, http://127.0.0.1:${port}`); }); } exports.DEFAULT_VIEWPORT = screenshot.DEFAULT_VIEWPORT; exports.Screenshot = screenshot.Screenshot; exports.args = args; exports.cache = cache; exports.getLaunch = getLaunch; exports.getScreenshot = getScreenshot; exports.isHttp = isHttp; exports.isNumber = isNumber; exports.serverless = serverless; exports.startServer = startServer;