| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186 | 
							- "use strict";
 
- var utils     = require("./lib/utils");
 
- var debug     = require("debug")("resp-mod");
 
- function RespModifier (opts) {
 
-     // options
 
-     opts               = opts || {};
 
-     opts.blacklist     = utils.toArray(opts.blacklist)     || [];
 
-     opts.whitelist     = utils.toArray(opts.whitelist)     || [];
 
-     opts.hostBlacklist = utils.toArray(opts.hostBlacklist) || [];
 
-     opts.rules         = opts.rules                        || [];
 
-     opts.ignore        = opts.ignore || opts.excludeList   || utils.defaultIgnoreTypes;
 
-     // helper functions
 
-     opts.regex = (function () {
 
-         var matches = opts.rules.map(function (item) {
 
-             return item.match.source;
 
-         }).join("|");
 
-         return new RegExp(matches);
 
-     })();
 
-     var respMod        = this;
 
-     respMod.opts       = opts;
 
-     respMod.middleware = respModifierMiddleware;
 
-     respMod.update = function (key, value) {
 
-         if (respMod.opts[key]) {
 
-             respMod.opts[key] = value;
 
-         }
 
-         return respMod;
 
-     };
 
-     function respModifierMiddleware(req, res, next) {
 
-         if (res._respModifier) {
 
-             debug("Reject req", req.url);
 
-             return next();
 
-         }
 
-         debug("Accept req", req.url);
 
-         res._respModifier = true;
 
-         var writeHead   = res.writeHead;
 
-         var runPatches  = true;
 
-         var write       = res.write;
 
-         var end         = res.end;
 
-         var singlerules = utils.isWhiteListedForSingle(req.url, respMod.opts.rules);
 
-         var withoutSingle = respMod.opts.rules.filter(function (rule) {
 
-             if (rule.paths && rule.paths.length) {
 
-                 return false;
 
-             }
 
-             return true;
 
-         });
 
-         /**
 
-          * Exit early for blacklisted domains
 
-          */
 
-         if (respMod.opts.hostBlacklist.indexOf(req.headers.host) > -1) {
 
-             return next();
 
-         }
 
-         if (singlerules.length) {
 
-             modifyResponse(singlerules, true);
 
-         } else {
 
-             if (utils.isWhitelisted(req.url, respMod.opts.whitelist)) {
 
-                 modifyResponse(withoutSingle, true);
 
-             } else {
 
-                 if (!utils.hasAcceptHeaders(req) || utils.inBlackList(req.url, respMod.opts)) {
 
-                     debug("Black listed or no text/html headers", req.url);
 
-                     return next();
 
-                 } else {
 
-                     modifyResponse(withoutSingle);
 
-                 }
 
-             }
 
-         }
 
-         next();
 
-         /**
 
-          * Actually do the overwrite
 
-          * @param {Array} rules
 
-          * @param {Boolean} [force] - if true, will always attempt to perform
 
-          * an overwrite - regardless of whether it appears to be HTML or not
 
-          */
 
-         function modifyResponse(rules, force) {
 
-             req.headers["accept-encoding"] = "identity";
 
-             function restore() {
 
-                 res.writeHead = writeHead;
 
-                 res.write = write;
 
-                 res.end = end;
 
-             }
 
-             res.push = function (chunk) {
 
-                 res.data = (res.data || "") + chunk;
 
-             };
 
-             res.write = function (string, encoding) {
 
-                 if (!runPatches) {
 
-                     return write.call(res, string, encoding);
 
-                 }
 
-                 if (string !== undefined) {
 
-                     var body = string instanceof Buffer ? string.toString(encoding) : string;
 
-                     // If this chunk appears to be valid, push onto the res.data stack
 
-                     if (force || (utils.isHtml(body) || utils.isHtml(res.data))) {
 
-                         res.push(body);
 
-                     } else {
 
-                         restore();
 
-                         return write.call(res, string, encoding);
 
-                     }
 
-                 }
 
-                 return true;
 
-             };
 
-             res.writeHead = function () {
 
-                 if (!runPatches) {
 
-                     return writeHead.apply(res, arguments);
 
-                 }
 
-                 var headers = arguments[arguments.length - 1];
 
-                 if (typeof headers === "object") {
 
-                     for (var name in headers) {
 
-                         if (/content-length/i.test(name)) {
 
-                             delete headers[name];
 
-                         }
 
-                     }
 
-                 }
 
-                 if (res.getHeader("content-length")) {
 
-                     res.removeHeader("content-length");
 
-                 }
 
-                 writeHead.apply(res, arguments);
 
-             };
 
-             res.end = function (string, encoding) {
 
-                 res.data = res.data || "";
 
-                 if (typeof string === "string") {
 
-                     res.data += string;
 
-                 }
 
-                 if (string instanceof Buffer) {
 
-                     res.data += string.toString();
 
-                 }
 
-                 if (!runPatches) {
 
-                     return end.call(res, string, encoding);
 
-                 }
 
-                 // Check if our body is HTML, and if it does not already have the snippet.
 
-                 if (force || utils.isHtml(res.data) && !utils.snip(res.data)) {
 
-                     // Include, if necessary, replacing the entire res.data with the included snippet.
 
-                     res.data = utils.applyRules(rules, res.data, req, res);
 
-                     runPatches = false;
 
-                 }
 
-                 if (res.data !== undefined && !res._header) {
 
-                     res.setHeader("content-length", Buffer.byteLength(res.data, encoding));
 
-                 }
 
-                 end.call(res, res.data, encoding);
 
-             };
 
-         }
 
-     }
 
-     return respMod;
 
- }
 
- module.exports = function (opts) {
 
-     var resp = new RespModifier(opts);
 
-     return resp.middleware;
 
- };
 
- module.exports.create = function (opts) {
 
-     var resp = new RespModifier(opts);
 
-     return resp;
 
- };
 
- module.exports.utils = utils;
 
 
  |