proxy
Advanced tools
Comparing version 0.2.1 to 0.2.2
@@ -0,5 +1,15 @@ | ||
0.2.2 / 2014-04-03 | ||
================== | ||
* History: match `git changelog` styling | ||
* package: update outdated deps | ||
* proxy: remove double semicolon | ||
* proxy: refactor to make the named functions be top-level | ||
* proxy: add a few debug() calls | ||
0.2.1 / 2013-09-16 | ||
================== | ||
- Close the socket after a CONNECT authorization request | ||
* Close the socket after a CONNECT authorization request | ||
@@ -9,4 +19,4 @@ 0.2.0 / 2013-09-10 | ||
- Fix calling the setup() function without any arguments | ||
- Initial integration of "commander" for the `proxy(1)` program | ||
* Fix calling the setup() function without any arguments | ||
* Initial integration of "commander" for the `proxy(1)` program | ||
@@ -16,9 +26,9 @@ 0.1.0 / 2013-09-09 | ||
- Added "Via" header | ||
- Added "X-Forwared-For" header | ||
- Strip hop-by-hop headers from requests and responses | ||
- Better tests (no longer reach the internet) | ||
- Add `.travis.yml` file | ||
- Proxy headers as original casing with node >= v0.11.6 (`rawHeaders`) | ||
- bin: set the `process.title` to "proxy" | ||
* Added "Via" header | ||
* Added "X-Forwared-For" header | ||
* Strip hop-by-hop headers from requests and responses | ||
* Better tests (no longer reach the internet) | ||
* Add `.travis.yml` file | ||
* Proxy headers as original casing with node >= v0.11.6 (`rawHeaders`) | ||
* bin: set the `process.title` to "proxy" | ||
@@ -28,2 +38,2 @@ 0.0.1 / 2013-09-07 | ||
- Initial release | ||
* Initial release |
{ | ||
"name": "proxy", | ||
"version": "0.2.1", | ||
"version": "0.2.2", | ||
"description": "An HTTP proxy written with Node.js (think Squid)", | ||
@@ -31,4 +31,5 @@ "main": "proxy.js", | ||
"basic-auth-parser": "0.0.2", | ||
"commander": "2.0.0", | ||
"debug": "0.7.2" | ||
"commander": "2.2.0", | ||
"debug": "0.8.0", | ||
"mocha": "1.18.2" | ||
}, | ||
@@ -35,0 +36,0 @@ "devDependencies": { |
169
proxy.js
@@ -127,3 +127,3 @@ | ||
} | ||
if (!auth) return requestAuthorization(req, res);; | ||
if (!auth) return requestAuthorization(req, res); | ||
var parsed = url.parse(req.url); | ||
@@ -242,9 +242,10 @@ | ||
if (gotResponse) { | ||
// already sent a response to the original request... | ||
// just destroy the socket | ||
debug.response('already sent a response, just destroying the socket...'); | ||
socket.destroy(); | ||
} else if ('ENOTFOUND' == err.code) { | ||
debug.response('HTTP/1.1 404 Not Found'); | ||
res.writeHead(404); | ||
res.end(); | ||
} else { | ||
debug.response('HTTP/1.1 500 Internal Server Error'); | ||
res.writeHead(500); | ||
@@ -287,6 +288,91 @@ res.end(); | ||
var res; | ||
var target; | ||
var gotResponse = false; | ||
// define request socket event listeners | ||
function onclientclose (err) { | ||
debug.request('HTTP request %s socket "close" event', req.url); | ||
} | ||
socket.on('close', onclientclose); | ||
function onclientend () { | ||
debug.request('HTTP request %s socket "end" event', req.url); | ||
cleanup(); | ||
} | ||
function onclienterror (err) { | ||
debug.request('HTTP request %s socket "error" event:\n%s', req.url, err.stack || err); | ||
} | ||
socket.on('error', onclienterror); | ||
// define target socket event listeners | ||
function ontargetclose () { | ||
debug.proxyResponse('proxy target %s "close" event', req.url); | ||
cleanup(); | ||
socket.destroy(); | ||
} | ||
function ontargetend () { | ||
debug.proxyResponse('proxy target %s "end" event', req.url); | ||
cleanup(); | ||
} | ||
function ontargeterror (err) { | ||
debug.proxyResponse('proxy target %s "error" event:\n%s', req.url, err.stack || err); | ||
cleanup(); | ||
if (gotResponse) { | ||
debug.response('already sent a response, just destroying the socket...'); | ||
socket.destroy(); | ||
} else if ('ENOTFOUND' == err.code) { | ||
debug.response('HTTP/1.1 404 Not Found'); | ||
res.writeHead(404); | ||
res.end(); | ||
} else { | ||
debug.response('HTTP/1.1 500 Internal Server Error'); | ||
res.writeHead(500); | ||
res.end(); | ||
} | ||
} | ||
function ontargetconnect () { | ||
debug.proxyResponse('proxy target %s "connect" event', req.url); | ||
debug.response('HTTP/1.1 200 Connection established'); | ||
gotResponse = true; | ||
res.removeListener('finish', onfinish); | ||
res.writeHead(200, 'Connection established'); | ||
// HACK: force a flush of the HTTP header | ||
res._send(''); | ||
// relinquish control of the `socket` from the ServerResponse instance | ||
res.detachSocket(socket); | ||
// nullify the ServerResponse object, so that it can be cleaned | ||
// up before this socket proxying is completed | ||
res = null; | ||
socket.pipe(target); | ||
target.pipe(socket); | ||
} | ||
// cleans up event listeners for the `socket` and `target` sockets | ||
function cleanup () { | ||
debug.response('cleanup'); | ||
socket.removeListener('close', onclientclose); | ||
socket.removeListener('error', onclienterror); | ||
socket.removeListener('end', onclientend); | ||
if (target) { | ||
target.removeListener('connect', ontargetconnect); | ||
target.removeListener('close', ontargetclose); | ||
target.removeListener('error', ontargeterror); | ||
target.removeListener('end', ontargetend); | ||
} | ||
} | ||
// create the `res` instance for this request since Node.js | ||
// doesn't provide us with one :( | ||
// XXX: this is undocumented API, so it will break some day (ノಠ益ಠ)ノ彡┻━┻ | ||
var res = new http.ServerResponse(req); | ||
res = new http.ServerResponse(req); | ||
res.shouldKeepAlive = false; | ||
@@ -297,5 +383,2 @@ res.chunkedEncoding = false; | ||
// pause the socket during authentication so no data is lost | ||
socket.pause(); | ||
// called for the ServerResponse's "finish" event | ||
@@ -313,2 +396,5 @@ // XXX: normally, node's "http" module has a "finish" event listener that would | ||
// pause the socket during authentication so no data is lost | ||
socket.pause(); | ||
authenticate(this, req, function (err, auth) { | ||
@@ -322,3 +408,3 @@ socket.resume(); | ||
} | ||
if (!auth) return requestAuthorization(req, res);; | ||
if (!auth) return requestAuthorization(req, res); | ||
@@ -329,64 +415,9 @@ var parts = req.url.split(':'); | ||
var opts = { host: host, port: port }; | ||
var gotResponse = false; | ||
function onconnect () { | ||
debug.proxyResponse('proxy target %s "connect" event', req.url); | ||
debug.response('HTTP/1.1 200 Connection established'); | ||
gotResponse = true; | ||
res.removeListener('finish', onfinish); | ||
res.writeHead(200, 'Connection established'); | ||
// HACK: force a flush of the HTTP header | ||
res._send(''); | ||
// relinquish control of the `socket` from the ServerResponse instance | ||
res.detachSocket(socket); | ||
socket.pipe(destination); | ||
destination.pipe(socket); | ||
} | ||
function onclose () { | ||
debug.proxyResponse('proxy target %s "close" event', req.url); | ||
cleanup(); | ||
socket.destroy(); | ||
} | ||
function onend () { | ||
debug.proxyResponse('proxy target %s "end" event', req.url); | ||
cleanup(); | ||
} | ||
function onerror (err) { | ||
debug.proxyResponse('proxy target %s "error" event:\n%s', req.url, err.stack || err); | ||
cleanup(); | ||
if (gotResponse) { | ||
debug.response('already sent a response, just destroying the socket...'); | ||
socket.destroy(); | ||
} else if ('ENOTFOUND' == err.code) { | ||
debug.response('HTTP/1.1 404 Not Found'); | ||
res.writeHead(404); | ||
res.end(); | ||
} else { | ||
debug.response('HTTP/1.1 500 Internal Server Error'); | ||
res.writeHead(500); | ||
res.end(); | ||
} | ||
} | ||
function cleanup () { | ||
debug.response('cleanup'); | ||
destination.removeListener('connect', onconnect); | ||
destination.removeListener('close', onclose); | ||
destination.removeListener('error', onerror); | ||
destination.removeListener('end', onend); | ||
} | ||
debug.proxyRequest('connecting to proxy target %s', req.url); | ||
var destination = net.connect(opts); | ||
destination.on('connect', onconnect); | ||
destination.on('close', onclose); | ||
destination.on('error', onerror); | ||
destination.on('end', onend); | ||
debug.proxyRequest('connecting to proxy target %j', opts); | ||
target = net.connect(opts); | ||
target.on('connect', ontargetconnect); | ||
target.on('close', ontargetclose); | ||
target.on('error', ontargeterror); | ||
target.on('end', ontargetend); | ||
}); | ||
@@ -393,0 +424,0 @@ } |
26261
558
4
+ Addedmocha@1.18.2
+ Addedcommander@0.6.12.2.0(transitive)
+ Addeddebug@0.8.0(transitive)
+ Addeddiff@1.0.7(transitive)
+ Addedglob@3.2.3(transitive)
+ Addedgraceful-fs@2.0.3(transitive)
+ Addedgrowl@1.7.0(transitive)
+ Addedinherits@2.0.4(transitive)
+ Addedjade@0.26.3(transitive)
+ Addedlru-cache@2.7.3(transitive)
+ Addedminimatch@0.2.14(transitive)
+ Addedmkdirp@0.3.00.3.5(transitive)
+ Addedmocha@1.18.2(transitive)
+ Addedsigmund@1.0.1(transitive)
- Removeddebug@0.7.2(transitive)
Updatedcommander@2.2.0
Updateddebug@0.8.0