Repository URL to install this package:
|
Version:
1.1.14 ▾
|
const { isFunction } = require('uxui-modules/exotic')
module.exports = function interceptFor(fn) {
// const debug = require('uxui-modules/_forks/debug')('express-interceptor')
// eslint-disable-next-line
return function interceptionMiddleware(req, res, next) {
const methods = fn(req, res)
_validateParams(methods)
const originalEnd = res.end
const originalWrite = res.write
const chunks = []
let isFirstWrite = true
let isIntercepting
// eslint-disable-next-line
function intercept(rawChunk, encoding) {
if (isFirstWrite) {
isFirstWrite = false
isIntercepting = methods.isInterceptable()
}
// debug('isIntercepting? %s', isIntercepting)
if (isIntercepting) {
// collect all the parts of a response
if (rawChunk) {
let chunk = rawChunk
if (
rawChunk !== null &&
!Buffer.isBuffer(chunk) &&
encoding !== 'buffer'
) {
if (!encoding) {
chunk = new Buffer(rawChunk)
} else {
chunk = new Buffer(rawChunk, encoding)
}
}
chunks.push(chunk)
}
// @todo @hack - very bad scope leak
if (typeof cb === 'object') {
cb()
}
}
return isIntercepting
}
res.write = function onWrite(chunk, encoding, cb) {
// debug('write called')
if (!intercept(chunk, encoding)) {
originalWrite.apply(res, arguments)
}
}
function afterSend(oldBody, newBody) {
if (isFunction(methods.afterSend)) {
const onTick = () => {
// debug(
// 'methods.afterSend running now, body size: %s %s',
// oldBody.length,
// newBody.length
// )
methods.afterSend(oldBody, newBody)
}
process.nextTick(onTick)
}
}
// eslint-disable-next-line
res.end = function onResEnd(chunk, encoding, cb) {
// debug('end called')
const args = Array.prototype.slice.call(arguments)
if (intercept(chunk, encoding)) {
isIntercepting = false
const oldBody = Buffer.concat(chunks).toString('utf-8')
if (methods.intercept) {
if (typeof methods.intercept !== 'function') {
throw new Error(
'`send` must be a function with the body to be sent as the only param'
)
}
res.removeHeader('Content-Length')
// allow the user to re-write response
const onIntercept = newBody => {
args[0] = newBody
originalEnd.apply(res, args)
afterSend(oldBody, newBody)
}
methods.intercept(oldBody, onIntercept)
} else {
// debug(' methods.send isnt defined')
afterSend(oldBody, oldBody)
originalEnd.apply(res, args)
}
} else {
originalEnd.apply(res, args)
}
}
next()
}
}
const VALID_PARAMS = ['isInterceptable', 'intercept', 'afterSend']
function _validateParams(methods) {
for (const k in methods) {
if (VALID_PARAMS.indexOf(k) < 0) {
throw new Error(
k + " isn't a valid param (" + VALID_PARAMS.join(', ') + ')'
)
}
}
if (!('isInterceptable' in methods)) {
throw 'isInterceptable is a required param (function)'
}
}