resume-server / src /services /browser.js
hari7775's picture
refactor: split index.js into modules; render Extracurricular Activities in PDFs
12d3f0e
Raw History Blame Contribute Delete
3.05 kB
import puppeteer from 'puppeteer';
import { BROWSER_LAUNCH_ARGS } from '../config.js';
let browser;
// One shared Chromium instance, relaunched if it disconnects
export async function getBrowser() {
if (!browser || !browser.connected) {
if (browser) await browser.close().catch(() => {});
console.log('Launching new browser instance...');
browser = await puppeteer.launch({
headless: 'new',
executablePath: process.env.PUPPETEER_EXECUTABLE_PATH || undefined,
args: BROWSER_LAUNCH_ARGS
});
}
return browser;
}
// Helper to block SSRF, metadata endpoints, and local file access
export async function setupPageSecurity(page) {
await page.setRequestInterception(true);
page.on('request', (req) => {
const urlStr = req.url();
try {
const parsedUrl = new URL(urlStr);
const protocol = parsedUrl.protocol.toLowerCase();
const hostname = parsedUrl.hostname.toLowerCase();
// Block file://, ftp://, and other non-web protocols
if (protocol !== 'http:' && protocol !== 'https:' && protocol !== 'data:' && protocol !== 'blob:') {
return req.abort();
}
// Block cloud metadata services and local network access
const blockedHosts = ['169.254.169.254', 'metadata.google.internal', 'localhost', '127.0.0.1', '0.0.0.0', '::1'];
if (blockedHosts.includes(hostname) || hostname.startsWith('10.') || hostname.startsWith('192.168.') || hostname.startsWith('172.16.')) {
console.warn(`[Security Block] Blocked SSRF attempt to: ${urlStr}`);
return req.abort();
}
req.continue();
} catch {
// If URL is invalid or unparseable and not data/blob, abort
if (!urlStr.startsWith('data:') && !urlStr.startsWith('blob:')) {
return req.abort();
}
req.continue();
}
});
}
// ── Startup smoke test: verify Chromium can actually launch ──
export async function verifyChromiumLaunch() {
try {
console.log('[Startup] Testing Chromium launch...');
console.log('[Startup] PUPPETEER_EXECUTABLE_PATH =', process.env.PUPPETEER_EXECUTABLE_PATH || '(not set, using bundled)');
console.log('[Startup] PUPPETEER_CACHE_DIR =', process.env.PUPPETEER_CACHE_DIR || '(not set)');
const testBrowser = await puppeteer.launch({
headless: 'new',
executablePath: process.env.PUPPETEER_EXECUTABLE_PATH || undefined,
args: ['--no-sandbox', '--disable-setuid-sandbox', '--disable-dev-shm-usage', '--disable-gpu']
});
const version = await testBrowser.version();
console.log(`[Startup] βœ… Chromium launched successfully: ${version}`);
await testBrowser.close();
} catch (err) {
console.error('[Startup] ❌ Chromium launch FAILED:', err.message);
console.error('[Startup] Full error:', err);
}
}