Last active
October 15, 2015 08:44
-
-
Save geekingfrog/cfec24819a7c21d85f59 to your computer and use it in GitHub Desktop.
simple http duplicator
This file contains hidden or 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
const forward = {host: 'duckduckgo.com', port: 80}; | |
const duplicates = [{host: 'google.com', port: 80}]; | |
const trace = console.trace.bind(console); | |
process.on('uncaughtException', console.trace.bind(console, 'uncaught exception:')); | |
const http = require('http'); | |
const request = require('request'); | |
const dns = require('dns'); | |
const Promise = require('bluebird'); | |
const memoizedDns = (function wrapper() { | |
const cache = new Map(); | |
const lookup = Promise.promisify(dns.lookup, dns); | |
const maxTs = 5000; | |
return function memoizedDnsWrapped(url) { | |
const isCached = cache.get(url); | |
const isInFlight = isCached && !cache.get(url).ts; | |
const isStale = isCached && Date.now() - cache.get(url).ts > maxTs; | |
if (isInFlight) return cache.get(url); | |
if (isCached && !isStale) return cache.get(url).val; | |
console.log('looking up %s', url); | |
const result = lookup(url).timeout(2000).then(([ip]) => { | |
cache.set(url, { ts: Date.now(), val: Promise.resolve(ip) }); | |
console.log('%s resolved to %s', url, ip); | |
return ip; | |
}).catch(cache.delete(url)); | |
cache.set(url, result); | |
return result; | |
}; | |
})(); | |
const server = http.createServer((req, res) => { | |
console.log('got %s request to %s', req.method, req.url); | |
memoizedDns(forward.host) | |
.then((ip) =>{ | |
req.pipe(request({ | |
method: req.method, | |
url: `http://${ip}:${forward.port || 80}${req.url}`, | |
headers: req.headers, | |
}).on('error', () => trace.bind('socket hang up?'))).pipe(res) | |
.on('error', trace.bind('got error')); | |
}).catch(console.trace.bind(console, 'Error while forwarding')); | |
function dupRequest(dup) { | |
return ( | |
memoizedDns(dup.host) | |
.then((ip) => { | |
req.pipe(request({ | |
method: req.method, | |
url: `http://${ip}:${dup.port || 80}${req.url}`, | |
headers: req.headers, | |
}).once('error', (err) => { | |
console.error('error in dup request to :', dup.host, err); | |
trace(); | |
})); | |
}) | |
); | |
} | |
duplicates.map((dup) => { | |
dupRequest(dup).catch(trace.bind('Error while duplicating to ' + dup.host)); | |
}); | |
}); | |
const port = 80; | |
server.listen(port, (err) => { | |
if (err) { | |
console.error('error while starting:', err); | |
process.exit(1); | |
} | |
console.log(`started on port ${port}`); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment