info: socket.io started debug: client authorized info: handshake authorized Gej626w0ImW0-t55HLAc debug: setting request GET /socket.io/1/websocket/Gej626w0ImW0-t55HLAc debug: set heartbeat interval for client Gej626w0ImW0-t55HLAc debug: client authorized for debug: websocket writing 1:: debug: websocket writing 5:::{"name":"outgoing","args":["Hello over websockets"]} Coverage

Coverage

90%
148
134
14

/home/cronopio/Nodejitsu/node-http-proxy/lib/http-proxy.js

100%
3
3
0
LineHitsSource
11var http = require('http'),
2 https = require('https'),
3 url = require('url'),
4 httpProxy = require('./http-proxy/'),
5 proxy = exports;
6
7/**
8 * Creates the proxy server.
9 *
10 * Examples:
11 *
12 * httpProxy.createProxyServer({ .. }, 8000)
13 * // => '{ web: [Function], ws: [Function] ... }'
14 *
15 * @param {Object} Options Config object passed to the proxy
16 *
17 * @return {Object} Proxy Proxy object with handlers for `ws` and `web` requests
18 *
19 * @api public
20 */
21
221proxy.createProxyServer = proxy.createServer = function createProxyServer(options) {
23 /*
24 * `options` is needed and it must have the following layout:
25 *
26 * {
27 * target : <url string to be parsed with the url module>
28 * forward: <url string to be parsed with the url module>
29 * agent : <object to be passed to http(s).request>
30 * ssl : <object to be passed to https.createServer()>
31 * ws : <true/false, if you want to proxy websockets>
32 * xfwd : <true/false, adds x-forward headers>
33 * secure : <true/false, verify SSL certificate>
34 * }
35 *
36 * NOTE: `options.ws` and `options.ssl` are optional.
37 * `options.target and `options.forward` cannot be
38 * both missing
39 * }
40 */
41
4216 return new httpProxy.Server(options);
43};
44
45

/home/cronopio/Nodejitsu/node-http-proxy/lib/http-proxy/common.js

100%
19
19
0
LineHitsSource
11var common = exports,
2 extend = require('util')._extend;
3
4/**
5 * Copies the right headers from `options` and `req` to
6 * `outgoing` which is then used to fire the proxied
7 * request.
8 *
9 * Examples:
10 *
11 * common.setupOutgoing(outgoing, options, req)
12 * // => { host: ..., hostname: ...}
13 *
14 * @param {Object} Outgoing Base object to be filled with required properties
15 * @param {Object} Options Config object passed to the proxy
16 * @param {ClientRequest} Req Request Object
17 * @param {String} Forward String to select forward or target
18
19 * @return {Object} Outgoing Object with all required properties set
20 *
21 * @api private
22 */
23
241common.setupOutgoing = function(outgoing, options, req, forward) {
2519 outgoing.port = options[forward || 'target'].port ||
26 (~['https:', 'wss:'].indexOf(options[forward || 'target'].protocol) ? 443 : 80);
27
2819 ['host', 'hostname', 'socketPath'].forEach(
2957 function(e) { outgoing[e] = options[forward || 'target'][e]; }
30 );
31
3219 ['method', 'headers'].forEach(
3338 function(e) { outgoing[e] = req[e]; }
34 );
35
3619 if (options.headers){
371 extend(outgoing.headers, options.headers);
38 }
39
4019 if (options[forward || 'target'].protocol == 'https:') {
414 outgoing.rejectUnauthorized = (typeof options.secure === "undefined") ? true : options.secure;
42 }
43
44
4519 outgoing.agent = options.agent || false;
4619 outgoing.path = req.url;
47
4819 return outgoing;
49};
50
51/**
52 * Set the proper configuration for sockets,
53 * set no delay and set keep alive, also set
54 * the timeout to 0.
55 *
56 * Examples:
57 *
58 * common.setupSocket(socket)
59 * // => Socket
60 *
61 * @param {Socket} Socket instance to setup
62
63 * @return {Socket} Return the configured socket.
64 *
65 * @api private
66 */
67
681common.setupSocket = function(socket) {
695 socket.setTimeout(0);
705 socket.setNoDelay(true);
71
725 socket.setKeepAlive(true, 0);
73
745 return socket;
75};
76

/home/cronopio/Nodejitsu/node-http-proxy/lib/http-proxy/index.js

80%
51
41
10
LineHitsSource
11var httpProxy = exports,
2 extend = require('util')._extend,
3 parse_url = require('url').parse,
4 EE3 = require('eventemitter3').EventEmitter,
5 http = require('http'),
6 https = require('https'),
7 web = require('./passes/web-incoming'),
8 ws = require('./passes/ws-incoming');
9
101httpProxy.Server = ProxyServer;
11
12/**
13 * Returns a function that creates the loader for
14 * either `ws` or `web`'s passes.
15 *
16 * Examples:
17 *
18 * httpProxy.createRightProxy('ws')
19 * // => [Function]
20 *
21 * @param {String} Type Either 'ws' or 'web'
22
23 * @return {Function} Loader Function that when called returns an iterator for the right passes
24 *
25 * @api private
26 */
27
281function createRightProxy(type) {
2932 return function(options) {
3032 return function(req, res /*, [head], [opts] */) {
3116 var passes = (type === 'ws') ? this.wsPasses : this.webPasses,
32 args = [].slice.call(arguments),
33 cntr = args.length - 1,
34 head, cbl;
35
36 /* optional args parse begin */
3716 if(typeof args[cntr] === 'function') {
381 cbl = args[cntr];
39
401 cntr--;
41 }
42
4316 if(
44 !(args[cntr] instanceof Buffer) &&
45 args[cntr] !== res
46 ) {
47 //Copy global options
481 options = extend({}, options);
49 //Overwrite with request options
501 extend(options, args[cntr]);
51
521 cntr--;
53 }
54
5516 if(args[cntr] instanceof Buffer) {
562 head = args[cntr];
57 }
58
59 /* optional args parse end */
60
6116 ['target', 'forward'].forEach(function(e) {
6232 if (typeof options[e] === 'string')
6315 options[e] = parse_url(options[e]);
64 });
65
66
6716 for(var i=0; i < passes.length; i++) {
68 /**
69 * Call of passes functions
70 * pass(req, res, options, head)
71 *
72 * In WebSockets case the `res` variable
73 * refer to the connection socket
74 * pass(req, socket, options, head)
75 */
7664 if(passes[i](req, res, options, head, cbl ? false : this, cbl)) { // passes can return a truthy value to halt the loop
771 break;
78 }
79 }
80 };
81 };
82}
83
84
851function ProxyServer(options) {
8616 EE3.call(this);
87
8816 this.web = createRightProxy('web')(options);
8916 this.ws = createRightProxy('ws')(options);
9016 this.options = options;
91
9216 this.webPasses = Object.keys(web).map(function(pass) {
9364 return web[pass];
94 });
95
9616 this.wsPasses = Object.keys(ws).map(function(pass) {
9764 return ws[pass];
98 });
99}
100
1011require('util').inherits(ProxyServer, EE3);
102
1031ProxyServer.prototype.listen = function(port) {
10411 var self = this,
10510 closure = function(req, res) { self.web(req, res); };
106
10711 this._server = this.options.ssl ?
108 https.createServer(this.options.ssl, closure) :
109 http.createServer(closure);
110
11111 if(this.options.ws) {
1124 this._server.on('upgrade', function(req, socket, head) { self.ws(req, socket, head); });
113 }
114
11511 this._server.listen(port);
116
11711 return this;
118};
119
1201ProxyServer.prototype.before = function(passName, callback) {
1210 var i = false;
1220 this.passes.forEach(function(v, idx) {
1230 if(v.name === passName) i = idx;
124 })
125
1260 if(!i) throw new Error('No such pass');
127
1280 this.passes.splice(i, 0, callback);
129};
1301ProxyServer.prototype.after = function(passName, callback) {
1310 var i = false;
1320 this.passes.forEach(function(v, idx) {
1330 if(v.name === passName) i = idx;
134 })
135
1360 if(!i) throw new Error('No such pass');
137
1380 this.passes.splice(i++, 0, callback);
139};
140

/home/cronopio/Nodejitsu/node-http-proxy/lib/http-proxy/passes/web-incoming.js

100%
29
29
0
LineHitsSource
11var http = require('http'),
2 https = require('https'),
3 web_o = require('./web-outgoing'),
4 common = require('../common'),
5 passes = exports;
6
71web_o = Object.keys(web_o).map(function(pass) {
84 return web_o[pass];
9});
10
11/*!
12 * Array of passes.
13 *
14 * A `pass` is just a function that is executed on `req, res, options`
15 * so that you can easily add new checks while still keeping the base
16 * flexible.
17 */
18
191[ // <--
20
21 /**
22 * Sets `content-length` to '0' if request is of DELETE type.
23 *
24 * @param {ClientRequest} Req Request object
25 * @param {IncomingMessage} Res Response object
26 * @param {Object} Options Config object passed to the proxy
27 *
28 * @api private
29 */
30
31 function deleteLength(req, res, options) {
3215 if(req.method === 'DELETE' && !req.headers['content-length']) {
331 req.headers['content-length'] = '0';
34 }
35 },
36
37 /**
38 * Sets timeout in request socket if it was specified in options.
39 *
40 * @param {ClientRequest} Req Request object
41 * @param {IncomingMessage} Res Response object
42 * @param {Object} Options Config object passed to the proxy
43 *
44 * @api private
45 */
46
47 function timeout(req, res, options) {
4815 if(options.timeout) {
492 req.socket.setTimeout(options.timeout);
50 }
51 },
52
53 /**
54 * Sets `x-forwarded-*` headers if specified in config.
55 *
56 * @param {ClientRequest} Req Request object
57 * @param {IncomingMessage} Res Response object
58 * @param {Object} Options Config object passed to the proxy
59 *
60 * @api private
61 */
62
63 function XHeaders(req, res, options) {
6429 if(!options.xfwd) return;
65
661 var values = {
67 for : req.connection.remoteAddress || req.socket.remoteAddress,
68 port : req.connection.remotePort || req.socket.remotePort,
69 proto: req.isSpdy ? 'https' : (req.connection.pair ? 'https' : 'http')
70 };
71
721 ['for', 'port', 'proto'].forEach(function(header) {
733 req.headers['x-forwarded-' + header] =
74 (req.headers['x-forwarded-' + header] || '') +
75 (req.headers['x-forwarded-' + header] ? ',' : '') +
76 values[header];
77 });
78 },
79
80 /**
81 * Does the actual proxying. If `forward` is enabled fires up
82 * a ForwardStream, same happens for ProxyStream. The request
83 * just dies otherwise.
84 *
85 * @param {ClientRequest} Req Request object
86 * @param {IncomingMessage} Res Response object
87 * @param {Object} Options Config object passed to the proxy
88 *
89 * @api private
90 */
91
92 function stream(req, res, options, _, server, clb) {
9314 if(options.forward) {
94 // If forward enable, so just pipe the request
951 var forwardReq = (options.forward.protocol === 'https:' ? https : http).request(
96 common.setupOutgoing(options.ssl || {}, options, req, 'forward')
97 );
981 (options.buffer || req).pipe(forwardReq);
992 if(!options.target) { return res.end(); }
100 }
101
102 // Request initalization
10313 var proxyReq = (options.target.protocol === 'https:' ? https : http).request(
104 common.setupOutgoing(options.ssl || {}, options, req)
105 );
106
107 // Error Handler
10813 proxyReq.on('error', function(err){
1094 if(options.buffer) { options.buffer.destroy(); }
1104 if (clb) {
1111 clb(err);
112 } else {
1133 server.emit('error', err, req, res);
114 }
115 });
116
11713 (options.buffer || req).pipe(proxyReq);
118
11913 proxyReq.on('response', function(proxyRes) {
1207 server.emit('proxyRes', proxyRes);
1217 for(var i=0; i < web_o.length; i++) {
12228 if(web_o[i](req, res, proxyRes)) { break; }
123 }
124
1257 proxyRes.pipe(res);
126 });
127
128 //proxyReq.end();
129 }
130
131] // <--
132 .forEach(function(func) {
1334 passes[func.name] = func;
134 });
135

/home/cronopio/Nodejitsu/node-http-proxy/lib/http-proxy/passes/web-outgoing.js

100%
12
12
0
LineHitsSource
11var passes = exports;
2
3/*!
4 * Array of passes.
5 *
6 * A `pass` is just a function that is executed on `req, res, options`
7 * so that you can easily add new checks while still keeping the base
8 * flexible.
9 */
10
111[ // <--
12
13 /**
14 * If is a HTTP 1.0 request, remove chunk headers
15 *
16 * @param {ClientRequest} Req Request object
17 * @param {IncomingMessage} Res Response object
18 * @param {proxyResponse} Res Response object from the proxy request
19 *
20 * @api private
21 */
22 function removeChunked(req, res, proxyRes) {
238 if(req.httpVersion === '1.0') {
241 delete proxyRes.headers['transfer-encoding'];
25 }
26 },
27
28 /**
29 * If is a HTTP 1.0 request, set the correct connection header
30 * or if connection header not present, then use `keep-alive`
31 *
32 * @param {ClientRequest} Req Request object
33 * @param {IncomingMessage} Res Response object
34 * @param {proxyResponse} Res Response object from the proxy request
35 *
36 * @api private
37 */
38 function setConnection(req, res, proxyRes) {
3911 if (req.httpVersion === '1.0') {
402 proxyRes.headers.connection = req.headers.connection || 'close';
419 } else if (!proxyRes.headers.connection) {
422 proxyRes.headers.connection = req.headers.connection || 'keep-alive';
43 }
44 },
45
46 /**
47 * Copy headers from proxyResponse to response
48 * set each header in response object.
49 *
50 * @param {ClientRequest} Req Request object
51 * @param {IncomingMessage} Res Response object
52 * @param {proxyResponse} Res Response object from the proxy request
53 *
54 * @api private
55 */
56 function writeHeaders(req, res, proxyRes) {
578 Object.keys(proxyRes.headers).forEach(function(key) {
5829 res.setHeader(key, proxyRes.headers[key]);
59 });
60 },
61
62 /**
63 * Set the statusCode from the proxyResponse
64 *
65 * @param {ClientRequest} Req Request object
66 * @param {IncomingMessage} Res Response object
67 * @param {proxyResponse} Res Response object from the proxy request
68 *
69 * @api private
70 */
71 function writeStatusCode(req, res, proxyRes) {
728 res.writeHead(proxyRes.statusCode);
73 }
74
75] // <--
76 .forEach(function(func) {
774 passes[func.name] = func;
78 });
79

/home/cronopio/Nodejitsu/node-http-proxy/lib/http-proxy/passes/ws-incoming.js

88%
34
30
4
LineHitsSource
11var http = require('http'),
2 https = require('https'),
3 common = require('../common'),
4 passes = exports;
5
6/*!
7 * Array of passes.
8 *
9 * A `pass` is just a function that is executed on `req, socket, options`
10 * so that you can easily add new checks while still keeping the base
11 * flexible.
12 */
13
14/*
15 * Websockets Passes
16 *
17 */
18
191var passes = exports;
20
211[
22 /**
23 * WebSocket requests must have the `GET` method and
24 * the `upgrade:websocket` header
25 *
26 * @param {ClientRequest} Req Request object
27 * @param {Socket} Websocket
28 *
29 * @api private
30 */
31
32 function checkMethodAndHeader (req, socket) {
336 if (req.method !== 'GET' || !req.headers.upgrade) {
342 socket.destroy();
352 return true;
36 }
37
384 if (req.headers.upgrade.toLowerCase() !== 'websocket') {
391 socket.destroy();
401 return true;
41 }
42 },
43
44 /**
45 * Set the proper configuration for sockets,
46 * set no delay and set keep alive, also set
47 * the timeout to 0.
48 *
49 * @param {ClientRequest} Req Request object
50 * @param {Socket} Websocket
51 *
52 * @api private
53 */
54
55 function setupSocket(req, socket) {
563 socket.setTimeout(0);
573 socket.setNoDelay(true);
58
593 socket.setKeepAlive(true, 0);
60 },
61
62 /**
63 * Sets `x-forwarded-*` headers if specified in config.
64 *
65 * @param {ClientRequest} Req Request object
66 * @param {Socket} Websocket
67 * @param {Object} Options Config object passed to the proxy
68 *
69 * @api private
70 */
71
72 function XHeaders(req, socket, options) {
738 if(!options.xfwd) return;
74
752 var values = {
76 for : req.connection.remoteAddress || req.socket.remoteAddress,
77 port : req.connection.remotePort || req.socket.remotePort,
78 proto: req.connection.pair ? 'wss' : 'ws'
79 };
80
812 ['for', 'port', 'proto'].forEach(function(header) {
826 req.headers['x-forwarded-' + header] =
83 (req.headers['x-forwarded-' + header] || '') +
84 (req.headers['x-forwarded-' + header] ? ',' : '') +
85 values[header];
86 });
87 },
88
89 /**
90 * Does the actual proxying. Make the request and upgrade it
91 * send the Switching Protocols request and pipe the sockets.
92 *
93 * @param {ClientRequest} Req Request object
94 * @param {Socket} Websocket
95 * @param {Object} Options Config object passed to the proxy
96 *
97 * @api private
98 */
99 function stream(req, socket, options, server, head, clb) {
1002 common.setupSocket(socket);
101
1022 if (head && head.length) socket.unshift(head);
103
104
1052 var proxyReq = (~['https:', 'wss:'].indexOf(options.target.protocol) ? https : http).request(
106 common.setupOutgoing(options.ssl || {}, options, req)
107 );
108 // Error Handler
1092 proxyReq.on('error', onError);
110
1112 proxyReq.on('upgrade', function(proxyRes, proxySocket, proxyHead) {
1122 proxySocket.on('error', onError);
113
1142 common.setupSocket(proxySocket);
115
1163 if (proxyHead && proxyHead.length) proxySocket.unshift(proxyHead);
117
1182 socket.write('HTTP/1.1 101 Switching Protocols\r\n');
1192 socket.write(Object.keys(proxyRes.headers).map(function(i) {
1206 return i + ": " + proxyRes.headers[i];
121 }).join('\r\n') + '\r\n\r\n');
1222 proxySocket.pipe(socket).pipe(proxySocket);
123 });
124
1252 return proxyReq.end(); // XXX: CHECK IF THIS IS THIS CORRECT
126
1270 function onError(err) {
1280 if (clb) {
1290 clb(err);
130 } else {
1310 server.emit('error', err, req, socket);
132 }
133 }
134 }
135
136] // <--
137 .forEach(function(func) {
1384 passes[func.name] = func;
139 });
140