Skip to content

Commit 598fe2e

Browse files
committed
[api doc] Rebuilt httpProxy.createServer() with the newer high-level RoutingProxy API
1 parent 5927ecd commit 598fe2e

File tree

3 files changed

+103
-24
lines changed

3 files changed

+103
-24
lines changed
File renamed without changes.

lib/node-http-proxy.js

+102-23
Original file line numberDiff line numberDiff line change
@@ -56,12 +56,14 @@ var HttpProxy = exports.HttpProxy = require('./node-http-proxy/http-proxy'
5656
//
5757
exports.createServer = function () {
5858
var args = Array.prototype.slice.call(arguments),
59+
handlers = [],
5960
options = {},
60-
host, port,
61-
server, proxy,
62-
callback,
61+
message,
6362
handler,
64-
silent;
63+
server,
64+
proxy,
65+
host,
66+
port;
6567

6668
//
6769
// Liberally parse arguments of the form:
@@ -75,18 +77,50 @@ exports.createServer = function () {
7577
case 'string': host = arg; break;
7678
case 'number': port = arg; break;
7779
case 'object': options = arg || {}; break;
78-
case 'function': callback = arg; break;
80+
case 'function': handlers.push(arg); break;
7981
};
8082
});
8183

82-
if (!host && !port && !options) {
84+
//
85+
// Helper function to create intelligent error message(s)
86+
// for the very liberal arguments parsing performed by
87+
// `require('http-proxy').createServer()`.
88+
//
89+
function validArguments() {
90+
var conditions = {
91+
'port and host': function () {
92+
return port && host;
93+
},
94+
'options.target or options.router': function () {
95+
return options && (options.router ||
96+
(options.target && options.target.host && options.target.port));
97+
},
98+
'or proxy handlers': function () {
99+
return handlers && handlers.length;
100+
}
101+
}
102+
103+
var missing = Object.keys(conditions).filter(function (name) {
104+
return !conditions[name]();
105+
});
106+
107+
if (missing.length === 3) {
108+
message = 'Cannot proxy without ' + missing.join(', ');
109+
return false;
110+
}
111+
112+
return true;
113+
}
114+
115+
if (!validArguments()) {
83116
//
84-
// If `host`, `port` and `options` are all not passed, then
85-
// this server is improperly configured.
117+
// If `host`, `port` and `options` are all not passed (with valid
118+
// options) then this server is improperly configured.
86119
//
87-
throw new Error('Cannot proxy without port, host, or router.')
120+
throw new Error(message);
121+
return;
88122
}
89-
123+
90124
//
91125
// Hoist up any explicit `host` or `port` arguments
92126
// that have been passed in to the options we will
@@ -96,28 +130,57 @@ exports.createServer = function () {
96130
options.target.port = options.target.port || port;
97131
options.target.host = options.target.host || host;
98132

133+
if (options.target && options.target.host && options.target.port) {
134+
//
135+
// If an explicit `host` and `port` combination has been passed
136+
// to `.createServer()` then instantiate a hot-path optimized
137+
// `HttpProxy` object and add the "proxy" middleware layer.
138+
//
139+
proxy = new HttpProxy(options);
140+
handlers.push(function (req, res) {
141+
proxy.proxyRequest(req, res);
142+
});
143+
}
144+
else {
145+
//
146+
// If no explicit `host` or `port` combination has been passed then
147+
// we have to assume that this is a "go-anywhere" Proxy (i.e. a `RoutingProxy`).
148+
//
149+
proxy = new RoutingProxy(options);
150+
151+
if (options.router) {
152+
//
153+
// If a routing table has been supplied than we assume
154+
// the user intends us to add the "proxy" middleware layer
155+
// for them
156+
//
157+
handlers.push(function (req, res) {
158+
proxy.proxyRequest(req, res);
159+
});
160+
161+
proxy.on('routes', function (routes) {
162+
server.emit('routes', routes);
163+
});
164+
}
165+
}
166+
99167
//
100168
// Create the `http[s].Server` instance which will use
101169
// an instance of `httpProxy.HttpProxy`.
102170
//
103-
proxy = new HttpProxy(options);
104-
handler = callback
105-
? function (req, res) { callback(req, res, proxy) }
106-
: function (req, res) { proxy.proxyRequest(req, res) };
171+
handler = handlers.length > 1
172+
? exports.stack(handlers, proxy)
173+
: function (req, res) { handlers[0](req, res, proxy) };
107174

108175
server = options.https
109176
? https.createServer(options.https, handler)
110177
: http.createServer(handler);
111178

112-
//server.on('close', function () {
113-
// proxy.close();
114-
//});
115-
116-
proxy.on('routes', function (routes) {
117-
server.emit('routes', routes);
179+
server.on('close', function () {
180+
proxy.close();
118181
});
119182

120-
if (!callback) {
183+
if (handlers.length <= 1) {
121184
//
122185
// If an explicit callback has not been supplied then
123186
// automagically proxy the request using the `HttpProxy`
@@ -213,6 +276,13 @@ exports.setMaxSockets = function (value) {
213276

214277
//
215278
// ### function stack (middlewares, proxy)
279+
// #### @middlewares {Array} Array of functions to stack.
280+
// #### @proxy {HttpProxy|RoutingProxy} Proxy instance to
281+
// Iteratively build up a single handler to the `http.Server`
282+
// `request` event (i.e. `function (req, res)`) by wrapping
283+
// each middleware `layer` into a `child` middleware which
284+
// is in invoked by the parent (i.e. predecessor in the Array).
285+
//
216286
// adapted from https://github.com/creationix/stack
217287
//
218288
exports.stack = function stack (middlewares, proxy) {
@@ -235,9 +305,18 @@ exports.stack = function stack (middlewares, proxy) {
235305
return;
236306
}
237307

238-
child(req, res);
239-
}
308+
if (child) {
309+
child(req, res);
310+
}
311+
};
240312

313+
//
314+
// Set the prototype of the `next` function to the instance
315+
// of the `proxy` so that in can be used interchangably from
316+
// a `connect` style callback and a true `HttpProxy` object.
317+
//
318+
// e.g. `function (req, res, next)` vs. `function (req, res, proxy)`
319+
//
241320
next.__proto__ = proxy;
242321
layer(req, res, next);
243322
};

lib/node-http-proxy/http-proxy.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -671,7 +671,7 @@ HttpProxy.prototype.proxyWebSocketRequest = function (req, socket, head, buffer)
671671
//
672672
HttpProxy.prototype.close = function () {
673673
[this.forward, this.target].forEach(function (proxy) {
674-
if (proxy.agent) {
674+
if (proxy && proxy.agent) {
675675
proxy.agent.sockets.forEach(function (socket) {
676676
socket.end();
677677
});

0 commit comments

Comments
 (0)