Files
web-check/api/tech-stack.js

48 lines
1.7 KiB
JavaScript

import chromium from '@sparticuz/chromium';
import middleware from './_common/middleware.js';
// Wappalyzer reads CHROMIUM_BIN at module load, so we must resolve
// the path before importing it (hence the dynamic import in the handler)
const ensureChromiumBin = async () => {
if (process.env.CHROMIUM_BIN) return;
const envPath = process.env.CHROME_PATH || process.env.PUPPETEER_EXECUTABLE_PATH;
if (envPath) {
process.env.CHROMIUM_BIN = envPath;
return;
}
// On serverless, puppeteer has no cached binary, use @sparticuz/chromium
if (process.env.AWS_LAMBDA_FUNCTION_NAME || process.env.NETLIFY) {
process.env.CHROMIUM_BIN = await chromium.executablePath();
// Avoid conflict with @sparticuz/chromium's extraction path at /tmp/chromium
if (!process.env.CHROMIUM_DATA_DIR) {
process.env.CHROMIUM_DATA_DIR = '/tmp/chromium-data';
}
}
};
const techStackHandler = async (url) => {
await ensureChromiumBin();
const { default: Wappalyzer } = await import('wappalyzer');
const wappalyzer = new Wappalyzer({});
try {
await wappalyzer.init();
const site = await wappalyzer.open(url, {}, { local: {}, session: {} });
const results = await site.analyze();
if (!results.technologies || results.technologies.length === 0) {
throw new Error('Unable to find any technologies for site');
}
return results;
} catch (error) {
if (/ENOENT|Browser was not found|Could not find Chromium/i.test(error.message)) {
return { skipped: error.message };
}
throw new Error(error.message);
} finally {
await wappalyzer.destroy();
}
};
export const handler = middleware(techStackHandler);
export default handler;