node-http-mitm-proxy
node-http-mitm-proxy copied to clipboard
What is the good way to cancel the default behavior?
Examples:
proxy.onRequest(function(ctx, callback) {
// I want to answer the request myself, without making a request to a server
// callback() would create the request to the server with the ctx.proxyToServerRequestOptions
// callback();
// callback("Any error") would trigger a "Proxy error"
// callback("Any error");
// No callback may not be clean and may have side effect, like not calling next handlers
});
proxy.onResponseData(function(ctx, chunk, callback) {
// I want to collect all chunks without sending it to the client and then send something to the client at the ResponseEnd
// callback(chunk) would send the chunk to the client
// callback(null, chunk);
// callback(null, null) or callback(null, []) may break or at least send the headers and is not clean at all
// callback(null, null);
// callback(null, []);
// callback("Any error") would trigger a "Proxy error"
// callback("Any error");
// No callback may not be clean and may have side effect, like not calling next handlers and may lead to no responseEnd event
});
Maybe the best way is to rewrite the API with a switch to prevent default operation after the handler execution.
Maybe the most transparent and intuitive way would be to test the second parameter of the callback and cancel default behavior if it is equals to false
or null
(but not undefined
)
Since https://github.com/joeferner/node-http-mitm-proxy/commit/0e40d2d550e3d815f6ef516086a34a256a398400 the onResponseData callback could be called with null chunk without breaking.
@felicienfrancois Hm, not sure I understand the proposed solution to this. I have a simple use case, I want to cache requests in memory after they have been requested one time. I'm trying to do something like this:
var Proxy = require('http-mitm-proxy')
var proxy = Proxy()
var port = 8081
var cache = {}
var chunks = []
proxy.onError(function (ctx, err) {
console.error('proxy error:', err)
})
proxy.onRequest(function (ctx, callback) {
chunks = []
callback()
})
proxy.onResponseData(function (ctx, chunk, dataCallback) {
chunks.push(chunk)
return dataCallback(null, chunk)
})
proxy.onResponseEnd(function (ctx, endCallback) {
const req = ctx.clientToProxyRequest
const url = req.url
const host = req.headers.host
cache[host + url] = chunks
return endCallback(null, chunks)
})
proxy.listen({ port: port })
console.log('listening on ' + port)
But I'm struggling to understand how I can cancel out the request and just return the cached data. Any pointers on how I can achieve that?
As always, finding the answer five seconds after asking the question. Solved it by doing something like this:
proxy.onRequest(function (ctx, callback) {
const req = ctx.clientToProxyRequest
const url = req.url
const host = req.headers.host
if (cache[host + url] !== undefined) {
ctx.proxyToClientResponse.end(cache[host + url].join())
return
}
chunks = []
callback()
})
@VictorBjelkholm Yes, that's it. I would just warn you that several requests may be handled in parallel, so having a global chunks array may not be the good solution (it can be erased before the end of the response data by another request).
Instead, you should store the chunks in the context (which sticks to one request):
ctx.chunks = []
Or define the chunks array in the context of each request like in this example: https://github.com/joeferner/node-http-mitm-proxy/blob/master/test/processFullResponseBody.js
Hah, yeah, learned that the hard way yesterday and did exactly what you said! Thanks for sharing that here though.
On Thu, Nov 26, 2015 at 10:09 AM Félicien FRANCOIS [email protected] wrote:
@VictorBjelkholm https://github.com/VictorBjelkholm Yes, that's it. I would just warn you that several requests may be handled in parallel, so having a global chunks array may not be the good solution (it can be erased before the end of the response data by another request).
Instead, you should store the chunks in the context (which sticks to one request):
ctx.chunks = []
— Reply to this email directly or view it on GitHub https://github.com/joeferner/node-http-mitm-proxy/issues/24#issuecomment-159853748 .
@VictorBjelkholm
Or you can try ctx.proxyToClientResponse.writeHead(504, 'Proxy Error');
Also When connection is not stopped onResponseData is still trigged and all data are loaded
So try to download 5Mb file you will see that onResponseEnd is executed even if you cancel connection, and data are still transfer, client don't get data but proxy still transfer it
__ Best solution will be to close socket connection after error, not only on this example but on time-out an on error
My TMP solution:
ctx.proxyToClientResponse.writeHead(504, 'Proxy Error'); ctx.proxyToClientResponse.end(''); ctx.serverToProxyResponse.complete = true;