diff options
| author | navewindre <boneyaard@gmail.com> | 2026-02-11 02:05:39 +0100 |
|---|---|---|
| committer | navewindre <boneyaard@gmail.com> | 2026-02-11 02:05:39 +0100 |
| commit | d9d55620a6f4f44b2c5069da107b2b3b111390ed (patch) | |
| tree | fbee83ccabeee18a04a691d61b60f68e98fa6553 /web/renderer | |
| parent | 3032a8495174f4f583f52c4e9429b6d4d357dc0c (diff) | |
seo renderer
Diffstat (limited to 'web/renderer')
| -rw-r--r-- | web/renderer/index.js | 94 | ||||
| -rw-r--r-- | web/renderer/package.json | 15 | ||||
| -rwxr-xr-x | web/renderer/run.sh | 4 | ||||
| -rw-r--r-- | web/renderer/server.sh | 3 |
4 files changed, 116 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 ); + } ); +})(); diff --git a/web/renderer/package.json b/web/renderer/package.json new file mode 100644 index 0000000..1b92952 --- /dev/null +++ b/web/renderer/package.json @@ -0,0 +1,15 @@ +{ + "name": "renderer", + "version": "1.0.0", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "ISC", + "description": "", + "dependencies": { + "express": "^5.2.1", + "puppeteer": "^24.37.2" + } +} diff --git a/web/renderer/run.sh b/web/renderer/run.sh new file mode 100755 index 0000000..b67ca91 --- /dev/null +++ b/web/renderer/run.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +npm i +screen -m -d node index.js diff --git a/web/renderer/server.sh b/web/renderer/server.sh new file mode 100644 index 0000000..293c5fb --- /dev/null +++ b/web/renderer/server.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +node index.js |
