const express = require('express'); const { fetchHtml, extractSeo, extractMetaTags, extractOutgoingCalls, extractResultingUrl } = require('./scraper'); const dbOps = require('./database'); const { authenticateApiKey } = require('./middleware'); const { isBrowserConnected } = require('./browser'); const config = require('./config'); const router = express.Router(); // Main API endpoint router.get('/', authenticateApiKey, async (req, res) => { const { url, skipCache } = req.query; // Validate URL parameter if (!url) { return res.status(400).json({ error: 'Missing required parameter: url', }); } // Validate URL format let urlObj; try { urlObj = new URL(url); } catch (error) { return res.status(400).json({ error: 'Invalid URL format', }); } // Parse skipCache (accept 'true', '1', 'yes', etc.) const shouldSkipCache = skipCache === 'true' || skipCache === '1' || skipCache === 'yes'; try { const html = await fetchHtml(url, shouldSkipCache); res.setHeader('Content-Type', 'text/html; charset=utf-8'); res.send(html); } catch (error) { console.error('Request error:', error); res.status(500).json({ error: 'Failed to fetch webpage', message: error.message, }); } }); // Health check endpoint router.get('/health', async (req, res) => { res.json({ status: 'ok', cacheExpiryHours: config.CACHE_EXPIRY_HOURS, browserConnected: isBrowserConnected(), database: dbOps.getDbType(), }); }); // Cache stats endpoint router.get('/cache/stats', authenticateApiKey, async (req, res) => { try { const stats = await dbOps.getStats(); res.json(stats); } catch (error) { res.status(500).json({ error: error.message }); } }); // Clear cache endpoint (optional, for maintenance) router.delete('/cache', authenticateApiKey, async (req, res) => { try { const { url } = req.query; if (url) { const deleted = await dbOps.deleteByUrl(url); res.json({ deleted }); } else { // Clear all cache const deleted = await dbOps.deleteAll(); res.json({ deleted }); } } catch (error) { res.status(500).json({ error: error.message }); } }); // SEO extraction endpoint router.get('/seo', authenticateApiKey, async (req, res) => { const { url, skipCache } = req.query; // Validate URL parameter if (!url) { return res.status(400).json({ error: 'Missing required parameter: url', }); } // Validate URL format let urlObj; try { urlObj = new URL(url); } catch (error) { return res.status(400).json({ error: 'Invalid URL format', }); } // Parse skipCache (accept 'true', '1', 'yes', etc.) const shouldSkipCache = skipCache === 'true' || skipCache === '1' || skipCache === 'yes'; try { const seoData = await extractSeo(url, shouldSkipCache); res.json(seoData); } catch (error) { console.error('SEO extraction error:', error); res.status(500).json({ status: 'error', url: url, error: error.message, }); } }); // Meta tags extraction endpoint router.get('/meta', authenticateApiKey, async (req, res) => { const { url, skipCache } = req.query; // Validate URL parameter if (!url) { return res.status(400).json({ error: 'Missing required parameter: url', }); } // Validate URL format let urlObj; try { urlObj = new URL(url); } catch (error) { return res.status(400).json({ error: 'Invalid URL format', }); } // Parse skipCache (accept 'true', '1', 'yes', etc.) const shouldSkipCache = skipCache === 'true' || skipCache === '1' || skipCache === 'yes'; try { const metaData = await extractMetaTags(url, shouldSkipCache); res.json(metaData); } catch (error) { console.error('Meta tags extraction error:', error); res.status(500).json({ status: 'error', url: url, error: error.message, }); } }); // Outgoing calls capture endpoint router.get('/outgoing-calls', authenticateApiKey, async (req, res) => { const { url, skipCache } = req.query; // Validate URL parameter if (!url) { return res.status(400).json({ error: 'Missing required parameter: url', }); } // Validate URL format let urlObj; try { urlObj = new URL(url); } catch (error) { return res.status(400).json({ error: 'Invalid URL format', }); } // Parse skipCache (accept 'true', '1', 'yes', etc.) const shouldSkipCache = skipCache === 'true' || skipCache === '1' || skipCache === 'yes'; try { const callsData = await extractOutgoingCalls(url, shouldSkipCache); res.json(callsData); } catch (error) { console.error('Outgoing calls capture error:', error); res.status(500).json({ status: 'error', url: url, error: error.message, }); } }); // Resulting URL endpoint router.get('/resulting-url', authenticateApiKey, async (req, res) => { const { url, skipCache } = req.query; // Validate URL parameter if (!url) { return res.status(400).json({ error: 'Missing required parameter: url', }); } // Validate URL format let urlObj; try { urlObj = new URL(url); } catch (error) { return res.status(400).json({ error: 'Invalid URL format', }); } // Parse skipCache (accept 'true', '1', 'yes', etc.) const shouldSkipCache = skipCache === 'true' || skipCache === '1' || skipCache === 'yes'; try { const resultingUrlData = await extractResultingUrl(url, shouldSkipCache); res.json(resultingUrlData); } catch (error) { console.error('Resulting URL error:', error); res.status(500).json({ status: 'error', original_url: url, error: error.message, }); } }); module.exports = router;