UNPKG

http2-express-autopush

Version:
73 lines (72 loc) 2.53 kB
///<reference types='express'/> import * as path from 'path'; import * as fs from 'fs'; import staticServe from 'serve-static'; import * as h2Auto from 'h2-auto-push'; import * as cookie from 'cookie'; function isHttp2Request(req) { return !!req.stream; } function isHttp2Response(res) { return !!res.stream; } function isStatic(url, root) { try { const filePath = path.join(root, url); const stat = fs.statSync(filePath); return stat.isFile(); } catch (err) { return false; } } const CACHE_COOKIE_KEY = '__ap_cache__'; export default function serveAutoPush(root, staticOptions, cacheConfig) { if (!root) { throw Error('root path required'); } if (typeof root !== 'string') { throw Error('root path must be a string'); } const rootDir = path.resolve(root); let ap; if (cacheConfig) { ap = new h2Auto.AutoPush(root, cacheConfig); } else { ap = new h2Auto.AutoPush(root); } return [ async function (req, res, next) { if (isHttp2Request(req) && isHttp2Response(res)) { try { const reqPath = req.url; const reqStream = req.stream; const cookies = cookie.parse(req.headers['cookie'] || ''); const cacheKey = cookies[CACHE_COOKIE_KEY]; const { newCacheCookie, pushFn } = await ap.preprocessRequest(reqPath, reqStream, cacheKey); res.setHeader('set-cookie', cookie.serialize(CACHE_COOKIE_KEY, newCacheCookie, { path: '/' })); reqStream.on('pushError', err => { console.error('Error while pushing', err); }); const resStream = res.stream; if (isStatic(req.url, rootDir)) { ap.recordRequestPath(resStream.session, reqPath, true); } else { ap.recordRequestPath(resStream.session, reqPath, false); } pushFn().then(noop, noop); } catch (err) { console.error('Error while autopush', err); } } next(); }, staticServe(rootDir, staticOptions) ]; } function noop() { } module.exports = serveAutoPush; module.exports.default = serveAutoPush;