connect-injector

A middleware to inject content into any HTTP response.

connect-injector

A middleware to inject content into any HTTP response.

Install the module with: npm install connect-injector

The basic API looks like this:

var injector = require('connect-injector');
var middleware = injector(function when(reqres) {
  // for this request and repsonse 
  // return whether or not to enable injecting 
}, function converter(contentreqrescallback) {
  content // the entire response buffer 
  req // the HTTP request 
  res // the HTTP response 
  callback // (error, data) with the injected data 
});

And can be used like any other Connect and Express middleware. You need to make sure to use the injector middleware before the actual content is being written.

A very useful example for connect-injector is to add JSONP support to any application/json repsonse:

var injector = require('connect-injector');
var inject = injector(function(reqres) {
  var isJSON = res.getHeader('content-type').indexOf('application/json') !== -1;
  return isJSON && req.query.callback;
}, function(datareqrescallback) {
  callback(null, req.query.callback + '(' + data.toString() + ')');
});
 
// inject needs to be used before any middleware that writes to the response 
connect().use(connect.query()).use(inject).use(/* your other middleware here */);

Now any application/json response will be wrapped into a callback if given the callback=xyz query parameter.

Another use case would be to minify JavaScript files on the fly using UglifyJS:

var injector = require('connect-injector');
var connect = require('connect');
var UglifyJS = require('uglify-js');
// Cache for already uglified files 
var cache = {};
// Function that uglifies JavaScript code 
var uglify = function (code) {
  var toplevel = UglifyJS.parse(code);
 
  toplevel.figure_out_scope();
 
  var compressor = UglifyJS.Compressor({
    warnings: false
  });
  var compressed = toplevel.transform(compressor);
 
  compressed.figure_out_scope();
  compressed.compute_char_frequency();
  compressed.mangle_names();
 
  return compressed.print_to_string();
};
 
var inject = injector(function(reqres) {
  return res.getHeader('content-type').indexOf('application/javascript') !== -1;
}, function(datareqrescallback) {
  // Check the cache, uglify the code if not and add it 
  if(!cache[req.url]) {
    cache[req.url] = uglify(data.toString());
  }
 
  callback(null, cache[req.url]);
});
 
// inject needs to be used before any middleware that writes to the response 
var app = connect().use(inject).use(connect.static(__dirname + '/../test'));
 
app.listen(8080);

connect-injector is tested to work with http-proxy you can rewrite existing proxied content:

var httpProxy = require('http-proxy');
var connect = require('connect');
var injector = require('connect-injector');
var proxy = httpProxy.createProxyServer();
var inject = injector(function(reqres) {
  return res.getHeader('content-type').indexOf('text/html') === 0;
}, function(datareqrescallback) {
  callback(null, data.toString().replace('</body>', '<p>Powered by connect-injector</p></body>'));
});
var proxyMiddleware = function(reqres) {
  // You need to rewrite your host in order to be able to hit virtual hosts 
  req.headers.host = 'daffl.github.io';
  proxy.web(req, res, {
    target: 'http://daffl.github.io'
  });
};
 
var proxyApp = connect().use(inject).use(proxyMiddleware);
 
proxyApp.listen(8080);

After starting the server, check http://localhost:8080/connect-injector/dummycontent.html to see the injected content.

0.4.2

  • Fix for empty responses not trying to be rewritten (#13, #14)

0.4.1

  • Fix connect-injector to work with Node 0.10.32 (#11)
  • Add debug messages and remove header rewriting (#12)

0.4.0

  • Fix issue when using GZip and refactor to use Q and proper NodeJS callbacks (#9)

0.3.0

  • Injector works with HTTP proxy and GZipped content (#4, #7, #8)

0.2.3

  • Fix caching issues for response headers not being written if there is no body (#3)

0.2.2

  • Fix handling of responses with an empty body (#1)

0.2.1

  • Fix bug not setting isIntercepted properly

0.2.0

  • Allow chaining injectors
  • Unit tests and CI
  • Fixes for writing correct headers
  • Use stream-buffers instead of concatenating

0.1.0

  • Initial alpha release

Copyright (c) 2013 David Luecke
Licensed under the MIT license.