Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@dobesv
Created January 23, 2012 05:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dobesv/1661009 to your computer and use it in GitHub Desktop.
Save dobesv/1661009 to your computer and use it in GitHub Desktop.
Function to intercept the response from the next() call.
var events = require('events');
/**
* When operating as a middleware our "origin" server is the next handler in the chain. This
* patches the given response object so that when the next handler writes to it we treat that
* as a response from the origin server.
*
* This replaces the writeHead, setHeader, removeHeader, write and end methods
* on the given response so that it can store the response in the cache and returns
* an object that be used to listen for the next() handler writing data and to send
* data back to the client.
*
* @param res ServerResponse-like object to patch
* @return Object that emits 'response', 'data, 'end' events, and also provides writeHead(), write(),
* and end() methods to write back to the original response.
*/
function interceptResponse(res) {
var writeHead = res.writeHead,
write = res.write,
end = res.end,
setHeader = res.setHeader,
removeHeader = res.removeHeader;
var headers = {};
var statusCode = null;
var txn = this;
var ourResponse = new (events.EventEmitter)();
ourResponse.writeHead = function(sc, reason, headers) {
writeHead.call(res, sc, reason, headers);
};
ourResponse.write = function(chunk, encoding) {
write.call(res, chunk, encoding);
};
ourResponse.end = function(chunk, encoding) {
end.call(res, chunk.encoding);
};
function processHead() {
emitter.statusCode = statusCode;
emitter.headers = headers;
ourResponse.emit('response', emitter);
};
function onWriteOrEnd(chunk, encoding) {
if(statusCode === null) {
statusCode = res.statusCode; // Implicit headers and status code
processHead();
}
if(chunk) {
ourResponse.emit('data', chunk, encoding);
}
}
res.writeHead = function(sc, reason, hdrs) {
if(statusCode !== null) throw new Error('Called writeHead after write, writeHead, or end!');
headers = hdrs;
statusCode = sc || 200;
// TODO Process the reason
processHead();
};
res.setHeader = function(field, val) {
if(statusCode !== null) throw new Error('Called setHeader after write, writeHead, or end!');
// TODO This will undo connect's patch to special case Content-Type and Set-Cookie, might be a bad thing for connect users setting cookies ...
headers[field.toLowerCase()] = val;
};
res.removeHeader = function(field) {
if(statusCode !== null) throw new Error('Called removeHeader after write, writeHead, or end!');
delete headers[field.toLowerVase()];
};
res.write = function(chunk, encoding) {
onWriteOrEnd(chunk, encoding);
};
res.end = function(chunk, encoding) {
onWriteOrEnd(chunk, encoding);
res.writeHead = writeHead;
res.write = write;
res.end = end;
res.setHeader = setHeader;
res.removeHeader = removeHeader;
ourResponse.emit('end');
};
return ourResponse;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment