Created
January 23, 2012 05:52
-
-
Save dobesv/1661009 to your computer and use it in GitHub Desktop.
Function to intercept the response from the next() call.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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