UNPKG

hastily

Version:

express middleware to simulate fastly cdn

180 lines 13 kB
'use strict'; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const on_headers_1 = __importDefault(require("on-headers")); const logging_1 = require("./logging"); const log = logging_1.createLogger('splice'); /** * @hidden */ function splice(req, res, next, makeStream) { log.debug({ res }, 'splicing hastily into response for %s', req.originalUrl); let ended = false; let length; const listeners = []; let stream; const resEnd = res.end.bind(res); const resOn = res.on.bind(res); const resWrite = res.write.bind(res); const resFlush = typeof res.flush === 'function' ? res.flush.bind(res) : () => null; const tryImplicitHeader = (instance) => { try { instance._implicitHeader(); return true; } catch (e) { return false; } }; // flush res.flush = function flush() { log.debug('response.flush() called'); if (stream) { stream.flush(); } else { resFlush(); } }; // proxy res.write = function write(chunk, encoding) { log.debug('outgoing response.write() called with chunk of length %s', chunk.length); if (ended) { log.debug('response.write(): ended flag is true, returning'); return false; } if (!this._header) { log.debug('response.write(): this._header is false, calling this._implicitHeader()'); if (!tryImplicitHeader(this)) { return false; } } if (stream) { log.debug('res.write() has access to stream! writing buffer'); return stream.write(Buffer.from(chunk, encoding)); } log.debug('res.write() has no access to stream yet. calling underlying response'); return resWrite.call(this, chunk, encoding); }; res.end = function end(chunk, encoding) { log.debug('outgoing response.end() called'); if (ended) { log.debug('response.end(): ended is already true, returning'); return false; } if (!this._header) { log.debug('response.end(): this._header is false, checking content length'); if (!this.getHeader('Content-Length')) { length = chunkLength(chunk, encoding); log.debug('response.end(): no Content-Length, %s bytes and counting', length); } log.debug('response.end(): calling this._implicitHeader()'); if (tryImplicitHeader(this)) { log.debug('tryImplicitHeader succeeded'); } } if (!stream) { log.debug('response.end(): stream never became available'); return resEnd.call(this, chunk, encoding); } log.debug('response.end(): stream is available, flushing? %s', chunk); // mark ended ended = true; // write Buffer for Node.js 0.8 if (chunk) { log.debug('chunk of length %s exists in .end, writing it to stream', chunk.length); stream.end(Buffer.from(chunk, encoding)); } else { log.debug({ res }, 'no chunk exists in .end, ending stream clean'); stream.end(); } }; function addBufferedListener(type, listener) { log.debug('res.on called for "%s" event', type); if (!listeners || type !== 'drain') { log.debug('%s listeners, eventType %s, calling underlying res.on', listeners.length, type); return resOn.call(this, type, listener); } if (stream) { log.debug('res.on() has access to stream, passing listener'); return stream.on(type, listener); } log.debug('stream does not exist; buffering listeners for future stream'); listeners.push([type, listener]); return this; } res.on = addBufferedListener; const unsplice = () => { res.on = resOn; res.end = resEnd; res.write = resWrite; addListeners(res, resOn, listeners); listeners.length = 0; }; on_headers_1.default(res, function onResponseHeaders() { try { if (ended) { return; } stream = makeStream(); if (!stream) { // request is filtered unsplice(); return; } else { stream.on('error', () => { log.debug('stream error, unsplicing'); unsplice(); }); } // add buffered listeners to stream addListeners(stream, stream.on, listeners); // header fields res.removeHeader('Content-Length'); // compression stream.on('data', function onStreamData(chunk) { if (resWrite(chunk) === false) { stream.pause(); } }); stream.on('end', resEnd); resOn.call(res, 'drain', function onResponseDrain() { stream.resume(); }); } catch (e) { console.error(e); res.statusCode = 400; res.statusMessage = e.message; resEnd(); ended = true; } }); next(); } exports.default = splice; /** * Add bufferred listeners to stream * @private */ function addListeners(stream, on, listeners) { for (const listener of listeners) { on.apply(stream, listener); } } /** * Get the length of a given chunk */ function chunkLength(chunk, encoding) { if (!chunk) { return 0; } return !Buffer.isBuffer(chunk) ? Buffer.byteLength(chunk, encoding) : chunk.length; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3BsaWNlLXJlc3BvbnNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2xpYi9zcGxpY2UtcmVzcG9uc2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsWUFBWSxDQUFDOzs7OztBQUdiLDREQUFtQztBQUNuQyx1Q0FBeUM7QUFRekMsTUFBTSxHQUFHLEdBQUcsc0JBQVksQ0FBQyxRQUFRLENBQUMsQ0FBQztBQUVuQzs7R0FFRztBQUNILFNBQXdCLE1BQU0sQ0FDNUIsR0FBWSxFQUNaLEdBQXFCLEVBQ3JCLElBQXdCLEVBQ3hCLFVBQXFDO0lBRXJDLEdBQUcsQ0FBQyxLQUFLLENBQUMsRUFBRSxHQUFHLEVBQUUsRUFBRSx1Q0FBdUMsRUFBRSxHQUFHLENBQUMsV0FBVyxDQUFDLENBQUM7SUFDN0UsSUFBSSxLQUFLLEdBQUcsS0FBSyxDQUFDO0lBQ2xCLElBQUksTUFBTSxDQUFDO0lBQ1gsTUFBTSxTQUFTLEdBQWUsRUFBRSxDQUFDO0lBQ2pDLElBQUksTUFBMkIsQ0FBQztJQUVoQyxNQUFNLE1BQU0sR0FBRyxHQUFHLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNqQyxNQUFNLEtBQUssR0FBRyxHQUFHLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUMvQixNQUFNLFFBQVEsR0FBRyxHQUFHLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNyQyxNQUFNLFFBQVEsR0FDWixPQUFPLEdBQUcsQ0FBQyxLQUFLLEtBQUssVUFBVSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDO0lBRXJFLE1BQU0saUJBQWlCLEdBQUcsQ0FBQyxRQUEwQixFQUFXLEVBQUU7UUFDaEUsSUFBSTtZQUNGLFFBQVEsQ0FBQyxlQUFl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