const http = require( 'http' ); const fs = require( 'fs' ); const path = require( 'path' ); const crypto = require( 'crypto' ); const puppeteer = require( 'puppeteer' ); const express = require( 'express' ); const PORT = 6860; const CACHE_DIR = path.join( __dirname, 'cache' ); const host = "https://networkheaven.net"; const app = express(); if( !fs.existsSync( CACHE_DIR ) ) fs.mkdirSync( CACHE_DIR ); function hash( str ) { return crypto.createHash( 'sha1' ).update( str ).digest( 'hex' ); } let browser = null; let cache = async ( req, res ) => { const { url } = req; console.log( `incoming req from ${req.headers['user-agent']} for ${url}` ); const urlObj = new URL( req.url, host ); const target = urlObj.href; const key = hash( target ); const file = path.join( CACHE_DIR, key + '.html' ); if( fs.existsSync( file ) ) { const html = fs.readFileSync( file ); res.writeHead( 200, { 'content-type': 'text/html' } ); return res.end( html ); } try { const page = await browser.newPage(); const r = await page.goto( target, { waitUntil: 'networkidle2', timeout: 30000 } ); const html = await page.content(); console.log( "caching page: " + target ); fs.writeFileSync( file, html ); await page.close(); const headers = r.headers(); res.writeHead( 200, { 'content-type': headers['content-type'], 'date': headers['date'], 'etag': headers['etag'], } ); res.end( html ); } catch( e ) { res.writeHead( 500, { 'content-type': 'text/plain' } ); res.end( 'render failed: ' + e.message ); } } app.get( "/", cache ); app.get( /\/$/, cache ); app.get( /#$/, cache ); app.get( /^\/[^.]*$/, cache ); app.use( async ( req, res ) => { let url = new URL( req.url, host ); const r = await fetch( url.href ); if( r.ok ) { const html = await r.text(); const headers = []; for( const [k, v] of r.headers.entries() ) headers[k] = v; res.writeHead( 200, { 'content-type': headers['content-type'], 'date': headers['date'], 'etag': headers['etag'], } ); res.end( html ); } } ); (async () => { browser = await puppeteer.launch( { headless: 'new' } ); app.listen( PORT, async () => { console.log( "listening on http://localhost:" + PORT ); } ); })();