diff options
Diffstat (limited to 'web/renderer/index.js')
| -rw-r--r-- | web/renderer/index.js | 94 |
1 files changed, 94 insertions, 0 deletions
diff --git a/web/renderer/index.js b/web/renderer/index.js new file mode 100644 index 0000000..03caa1c --- /dev/null +++ b/web/renderer/index.js @@ -0,0 +1,94 @@ +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 ); + } ); +})(); |
