cloudcms-server 0.9.270 → 0.9.271

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/middleware/proxy/proxy.js +5 -9
  2. package/package.json +2 -2
  3. package/temp/http-proxy/.auto-changelog +6 -0
  4. package/temp/http-proxy/.gitattributes +1 -0
  5. package/temp/http-proxy/CHANGELOG.md +1872 -0
  6. package/temp/http-proxy/CODE_OF_CONDUCT.md +74 -0
  7. package/temp/http-proxy/LICENSE +23 -0
  8. package/temp/http-proxy/README.md +568 -0
  9. package/temp/http-proxy/codecov.yml +10 -0
  10. package/temp/http-proxy/index.js +13 -0
  11. package/temp/http-proxy/lib/http-proxy/common.js +220 -0
  12. package/temp/http-proxy/lib/http-proxy/index.js +174 -0
  13. package/temp/http-proxy/lib/http-proxy/passes/web-incoming.js +174 -0
  14. package/temp/http-proxy/lib/http-proxy/passes/web-outgoing.js +135 -0
  15. package/temp/http-proxy/lib/http-proxy/passes/ws-incoming.js +141 -0
  16. package/temp/http-proxy/lib/index.js +13 -0
  17. package/temp/http-proxy/package.json +41 -0
  18. package/temp/http-proxy/renovate.json +19 -0
  19. package/temp/node-http-proxy/.eslintignore +3 -0
  20. package/temp/node-http-proxy/.eslintrc.js +21 -0
  21. package/temp/node-http-proxy/.github/workflows/ci.yml +30 -0
  22. package/temp/node-http-proxy/.prettierrc +7 -0
  23. package/temp/node-http-proxy/CODE_OF_CONDUCT.md +74 -0
  24. package/temp/node-http-proxy/LICENSE +23 -0
  25. package/temp/node-http-proxy/README.md +568 -0
  26. package/temp/node-http-proxy/codecov.yml +10 -0
  27. package/temp/node-http-proxy/dist/http-proxy/common.js +220 -0
  28. package/temp/node-http-proxy/dist/http-proxy/index.js +174 -0
  29. package/temp/node-http-proxy/dist/http-proxy/passes/web-incoming.js +174 -0
  30. package/temp/node-http-proxy/dist/http-proxy/passes/web-outgoing.js +135 -0
  31. package/temp/node-http-proxy/dist/http-proxy/passes/ws-incoming.js +141 -0
  32. package/temp/node-http-proxy/dist/index.js +13 -0
  33. package/temp/node-http-proxy/lib/http-proxy/common.js +265 -0
  34. package/temp/node-http-proxy/lib/http-proxy/index.ts +242 -0
  35. package/temp/node-http-proxy/lib/http-proxy/passes/web-incoming.js +208 -0
  36. package/temp/node-http-proxy/lib/http-proxy/passes/web-outgoing.js +163 -0
  37. package/temp/node-http-proxy/lib/http-proxy/passes/ws-incoming.js +179 -0
  38. package/temp/node-http-proxy/lib/index.ts +13 -0
  39. package/temp/node-http-proxy/lib/types.d.ts +277 -0
  40. package/temp/node-http-proxy/package-lock.json +5028 -0
  41. package/temp/node-http-proxy/package.json +47 -0
  42. package/temp/node-http-proxy/tsconfig.build.json +4 -0
  43. package/temp/node-http-proxy/tsconfig.json +115 -0
  44. package/temp/node-http-proxy/vitest.config.ts +9 -0
  45. package/util/proxy-factory.js +39 -128
@@ -0,0 +1,220 @@
1
+ "use strict";
2
+ const common = exports, url = require('url'), extend = require('util')._extend, required = require('requires-port');
3
+ const upgradeHeader = /(^|,)\s*upgrade\s*($|,)/i, isSSL = /^https|wss/;
4
+ /**
5
+ * Simple Regex for testing if protocol is https
6
+ */
7
+ common.isSSL = isSSL;
8
+ /**
9
+ * Copies the right headers from `options` and `req` to
10
+ * `outgoing` which is then used to fire the proxied
11
+ * request.
12
+ *
13
+ * Examples:
14
+ *
15
+ * common.setupOutgoing(outgoing, options, req)
16
+ * // => { host: ..., hostname: ...}
17
+ *
18
+ * @param {Object} Outgoing Base object to be filled with required properties
19
+ * @param {Object} Options Config object passed to the proxy
20
+ * @param {ClientRequest} Req Request Object
21
+ * @param {String} Forward String to select forward or target
22
+ *
23
+ * @return {Object} Outgoing Object with all required properties set
24
+ *
25
+ * @api private
26
+ */
27
+ common.setupOutgoing = function (outgoing, options, req, forward) {
28
+ outgoing.port =
29
+ options[forward || 'target'].port ||
30
+ (isSSL.test(options[forward || 'target'].protocol) ? 443 : 80);
31
+ [
32
+ 'host',
33
+ 'hostname',
34
+ 'socketPath',
35
+ 'pfx',
36
+ 'key',
37
+ 'passphrase',
38
+ 'cert',
39
+ 'ca',
40
+ 'ciphers',
41
+ 'secureProtocol',
42
+ ].forEach(function (e) {
43
+ outgoing[e] = options[forward || 'target'][e];
44
+ });
45
+ outgoing.method = options.method || req.method;
46
+ outgoing.headers = extend({}, req.headers);
47
+ if (options.headers) {
48
+ extend(outgoing.headers, options.headers);
49
+ }
50
+ if (options.auth) {
51
+ outgoing.auth = options.auth;
52
+ }
53
+ if (options.ca) {
54
+ outgoing.ca = options.ca;
55
+ }
56
+ if (isSSL.test(options[forward || 'target'].protocol)) {
57
+ outgoing.rejectUnauthorized =
58
+ typeof options.secure === 'undefined' ? true : options.secure;
59
+ }
60
+ outgoing.agent = options.agent || false;
61
+ outgoing.localAddress = options.localAddress;
62
+ //
63
+ // Remark: If we are false and not upgrading, set the connection: close. This is the right thing to do
64
+ // as node core doesn't handle this COMPLETELY properly yet.
65
+ //
66
+ if (!outgoing.agent) {
67
+ outgoing.headers = outgoing.headers || {};
68
+ if (typeof outgoing.headers.connection !== 'string' ||
69
+ !upgradeHeader.test(outgoing.headers.connection)) {
70
+ outgoing.headers.connection = 'close';
71
+ }
72
+ }
73
+ // the final path is target path + relative path requested by user:
74
+ const target = options[forward || 'target'];
75
+ const targetPath = target && options.prependPath !== false ? target.path || '' : '';
76
+ //
77
+ // Remark: Can we somehow not use url.parse as a perf optimization?
78
+ //
79
+ let outgoingPath = !options.toProxy ? url.parse(req.url).path || '' : req.url;
80
+ //
81
+ // Remark: ignorePath will just straight up ignore whatever the request's
82
+ // path is. This can be labeled as FOOT-GUN material if you do not know what
83
+ // you are doing and are using conflicting options.
84
+ //
85
+ outgoingPath = !options.ignorePath ? outgoingPath : '';
86
+ outgoing.path = common.urlJoin(targetPath, outgoingPath);
87
+ if (options.changeOrigin) {
88
+ outgoing.headers.host =
89
+ required(outgoing.port, options[forward || 'target'].protocol) &&
90
+ !hasPort(outgoing.host)
91
+ ? outgoing.host + ':' + outgoing.port
92
+ : outgoing.host;
93
+ }
94
+ return outgoing;
95
+ };
96
+ /**
97
+ * Set the proper configuration for sockets,
98
+ * set no delay and set keep alive, also set
99
+ * the timeout to 0.
100
+ *
101
+ * Examples:
102
+ *
103
+ * common.setupSocket(socket)
104
+ * // => Socket
105
+ *
106
+ * @param {Socket} Socket instance to setup
107
+ *
108
+ * @return {Socket} Return the configured socket.
109
+ *
110
+ * @api private
111
+ */
112
+ common.setupSocket = function (socket) {
113
+ socket.setTimeout(0);
114
+ socket.setNoDelay(true);
115
+ socket.setKeepAlive(true, 0);
116
+ return socket;
117
+ };
118
+ /**
119
+ * Get the port number from the host. Or guess it based on the connection type.
120
+ *
121
+ * @param {Request} req Incoming HTTP request.
122
+ *
123
+ * @return {String} The port number.
124
+ *
125
+ * @api private
126
+ */
127
+ common.getPort = function (req) {
128
+ const res = req.headers.host ? req.headers.host.match(/:(\d+)/) : '';
129
+ return res ? res[1] : common.hasEncryptedConnection(req) ? '443' : '80';
130
+ };
131
+ /**
132
+ * Check if the request has an encrypted connection.
133
+ *
134
+ * @param {Request} req Incoming HTTP request.
135
+ *
136
+ * @return {Boolean} Whether the connection is encrypted or not.
137
+ *
138
+ * @api private
139
+ */
140
+ common.hasEncryptedConnection = function (req) {
141
+ return Boolean(req.connection.encrypted || req.connection.pair);
142
+ };
143
+ /**
144
+ * OS-agnostic join (doesn't break on URLs like path.join does on Windows)>
145
+ *
146
+ * @return {String} The generated path.
147
+ *
148
+ * @api private
149
+ */
150
+ common.urlJoin = function () {
151
+ //
152
+ // We do not want to mess with the query string. All we want to touch is the path.
153
+ //
154
+ const args = Array.prototype.slice.call(arguments), lastIndex = args.length - 1, last = args[lastIndex], lastSegs = last.split('?');
155
+ args[lastIndex] = lastSegs.shift();
156
+ //
157
+ // Join all strings, but remove empty strings so we don't get extra slashes from
158
+ // joining e.g. ['', 'am']
159
+ //
160
+ const retSegs = [
161
+ args
162
+ .filter(Boolean)
163
+ .join('/')
164
+ .replace(/\/+/g, '/')
165
+ .replace('http:/', 'http://')
166
+ .replace('https:/', 'https://'),
167
+ ];
168
+ // Only join the query string if it exists so we don't have trailing a '?'
169
+ // on every request
170
+ // Handle case where there could be multiple ? in the URL.
171
+ retSegs.push.apply(retSegs, lastSegs);
172
+ return retSegs.join('?');
173
+ };
174
+ /**
175
+ * Rewrites or removes the domain of a cookie header
176
+ *
177
+ * @param {String|Array} header
178
+ * @param {Object} config, mapping of domain to rewritten domain.
179
+ * '*' key to match any domain, null value to remove the domain.
180
+ *
181
+ * @api private
182
+ */
183
+ common.rewriteCookieProperty = function rewriteCookieProperty(header, config, property) {
184
+ if (Array.isArray(header)) {
185
+ return header.map(function (headerElement) {
186
+ return rewriteCookieProperty(headerElement, config, property);
187
+ });
188
+ }
189
+ return header.replace(new RegExp('(;\\s*' + property + '=)([^;]+)', 'i'), function (match, prefix, previousValue) {
190
+ let newValue;
191
+ if (previousValue in config) {
192
+ newValue = config[previousValue];
193
+ }
194
+ else if ('*' in config) {
195
+ newValue = config['*'];
196
+ }
197
+ else {
198
+ //no match, return previous value
199
+ return match;
200
+ }
201
+ if (newValue) {
202
+ //replace value
203
+ return prefix + newValue;
204
+ }
205
+ else {
206
+ //remove value
207
+ return '';
208
+ }
209
+ });
210
+ };
211
+ /**
212
+ * Check the host and see if it potentially has a port in it (keep it simple)
213
+ *
214
+ * @returns {Boolean} Whether we have one or not
215
+ *
216
+ * @api private
217
+ */
218
+ function hasPort(host) {
219
+ return !!~host.indexOf(':');
220
+ }
@@ -0,0 +1,174 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.createServer = exports.createProxy = exports.createProxyServer = exports.ProxyServerNew = void 0;
7
+ const http_1 = __importDefault(require("http"));
8
+ const https_1 = __importDefault(require("https"));
9
+ const url_1 = require("url");
10
+ const eventemitter3_1 = __importDefault(require("eventemitter3"));
11
+ const web_incoming_1 = __importDefault(require("./passes/web-incoming"));
12
+ const ws_incoming_1 = __importDefault(require("./passes/ws-incoming"));
13
+ /**
14
+ * Returns a function that creates the loader for
15
+ * either `ws` or `web`'s passes.
16
+ *
17
+ * Examples:
18
+ *
19
+ * createRightProxy('ws')
20
+ * // => [Function]
21
+ *
22
+ * @param type
23
+ *
24
+ * @return Loader function that when called returns an iterator for the right passes
25
+ *
26
+ * @api private
27
+ */
28
+ function createRightProxy(type) {
29
+ return function (options) {
30
+ return function (req, resOrSocket) {
31
+ const passes = type === 'ws' ? this.wsPasses : this.webPasses,
32
+ // TODO: Migrate away from arguments.
33
+ // eslint-disable-next-line prefer-rest-params
34
+ args = [].slice.call(arguments);
35
+ let cntr = args.length - 1, head, cbl;
36
+ /* optional args parse begin */
37
+ if (typeof args[cntr] === 'function') {
38
+ cbl = args[cntr];
39
+ cntr--;
40
+ }
41
+ let requestOptions = options;
42
+ if (!(args[cntr] instanceof Buffer) && args[cntr] !== resOrSocket) {
43
+ //Copy global options
44
+ requestOptions = Object.assign({}, options);
45
+ //Overwrite with request options
46
+ Object.assign(requestOptions, args[cntr]);
47
+ cntr--;
48
+ }
49
+ if (args[cntr] instanceof Buffer) {
50
+ head = args[cntr];
51
+ }
52
+ /* optional args parse end */
53
+ ['target', 'forward'].forEach(function (e) {
54
+ if (typeof requestOptions[e] === 'string')
55
+ requestOptions[e] = (0, url_1.parse)(requestOptions[e]);
56
+ });
57
+ if (!requestOptions.target && !requestOptions.forward) {
58
+ this.emit('error', new Error('Must provide a proper URL as target'));
59
+ return;
60
+ }
61
+ for (let i = 0; i < passes.length; i++) {
62
+ /**
63
+ * Call of passes functions
64
+ * pass(req, res, options, head)
65
+ *
66
+ * In WebSockets case the `res` variable
67
+ * refer to the connection socket
68
+ * pass(req, socket, options, head)
69
+ */
70
+ // TODO: Figure out the typing here.
71
+ // @ts-ignore
72
+ if (passes[i](req, resOrSocket, requestOptions, head, this, cbl)) {
73
+ // passes can return a truthy value to halt the loop
74
+ break;
75
+ }
76
+ }
77
+ };
78
+ };
79
+ }
80
+ class ProxyServerNew extends eventemitter3_1.default {
81
+ constructor(options) {
82
+ super();
83
+ options = options || {};
84
+ options.prependPath = options.prependPath !== false;
85
+ this.web = createRightProxy('web')(options);
86
+ this.ws = createRightProxy('ws')(options);
87
+ this.options = options;
88
+ this.webPasses = Object.keys(web_incoming_1.default).map(function (pass) {
89
+ // TODO: Figure out the typing here.
90
+ return web_incoming_1.default[pass];
91
+ });
92
+ this.wsPasses = Object.keys(ws_incoming_1.default).map(function (pass) {
93
+ // TODO: Figure out the typing here.
94
+ return ws_incoming_1.default[pass];
95
+ });
96
+ this.on('error', this.onError, this);
97
+ }
98
+ after(type, passName, callback) {
99
+ const passes = type === 'ws' ? this.wsPasses : this.webPasses;
100
+ let i = -1;
101
+ passes.forEach((v, idx) => {
102
+ if (v.name === passName)
103
+ i = idx;
104
+ });
105
+ if (i === -1)
106
+ throw new Error('No such pass');
107
+ passes.splice(i++, 0, callback);
108
+ }
109
+ before(type, passName, callback) {
110
+ const passes = type === 'ws' ? this.wsPasses : this.webPasses;
111
+ let i = -1;
112
+ passes.forEach((v, idx) => {
113
+ if (v.name === passName)
114
+ i = idx;
115
+ });
116
+ if (i === -1)
117
+ throw new Error('No such pass');
118
+ passes.splice(i, 0, callback);
119
+ }
120
+ close(callback) {
121
+ if (this._server) {
122
+ this._server.close(() => {
123
+ this._server = undefined;
124
+ callback?.();
125
+ });
126
+ }
127
+ }
128
+ listen(port, hostname) {
129
+ const closure = (req, res) => {
130
+ this.web(req, res);
131
+ };
132
+ const server = this.options.ssl
133
+ ? https_1.default.createServer(this.options.ssl, closure)
134
+ : http_1.default.createServer(closure);
135
+ if (this.options.ws) {
136
+ server.on('upgrade', (req, socket, head) => {
137
+ this.ws(req, socket, head);
138
+ });
139
+ }
140
+ server.listen(port, hostname);
141
+ this._server = server;
142
+ return this;
143
+ }
144
+ onError(err) {
145
+ //
146
+ // Remark: Replicate node core behavior using EE3
147
+ // so we force people to handle their own errors
148
+ //
149
+ if (super.listeners('error').length === 1) {
150
+ throw err;
151
+ }
152
+ }
153
+ }
154
+ exports.ProxyServerNew = ProxyServerNew;
155
+ /**
156
+ * Creates the proxy server.
157
+ *
158
+ * Examples:
159
+ *
160
+ * httpProxy.createServer({ .. }, 8000)
161
+ * // => '{ web: [Function], ws: [Function] ... }'
162
+ *
163
+ * @param options Config object passed to the proxy
164
+ *
165
+ * @return Proxy object with handlers for `ws` and `web` requests
166
+ *
167
+ * @api public
168
+ */
169
+ function createProxyServer(options) {
170
+ return new ProxyServerNew(options);
171
+ }
172
+ exports.createProxyServer = createProxyServer;
173
+ exports.createProxy = createProxyServer;
174
+ exports.createServer = createProxyServer;
@@ -0,0 +1,174 @@
1
+ "use strict";
2
+ const httpNative = require('http'), httpsNative = require('https'), common = require('../common'), followRedirects = require('follow-redirects'), web_o = Object.values(require('./web-outgoing'));
3
+ const nativeAgents = { http: httpNative, https: httpsNative };
4
+ /*!
5
+ * Array of passes.
6
+ *
7
+ * A `pass` is just a function that is executed on `req, res, options`
8
+ * so that you can easily add new checks while still keeping the base
9
+ * flexible.
10
+ */
11
+ module.exports = {
12
+ /**
13
+ * Sets `content-length` to '0' if request is of DELETE type.
14
+ *
15
+ * @param {ClientRequest} req Request object
16
+ * @param {IncomingMessage} res Response object
17
+ * @param {object} options Config object passed to the proxy
18
+ *
19
+ * @api private
20
+ */
21
+ deleteLength: function deleteLength(req, res, options) {
22
+ if ((req.method === 'DELETE' || req.method === 'OPTIONS') &&
23
+ !req.headers['content-length']) {
24
+ req.headers['content-length'] = '0';
25
+ delete req.headers['transfer-encoding'];
26
+ }
27
+ },
28
+ /**
29
+ * Sets timeout in request socket if it was specified in options.
30
+ *
31
+ * @param {ClientRequest} req Request object
32
+ * @param {IncomingMessage} res Response object
33
+ * @param {object} options Config object passed to the proxy
34
+ *
35
+ * @api private
36
+ */
37
+ timeout: function timeout(req, res, options) {
38
+ if (options.timeout) {
39
+ req.socket.setTimeout(options.timeout);
40
+ }
41
+ },
42
+ /**
43
+ * Sets `x-forwarded-*` headers if specified in config.
44
+ *
45
+ * @param {ClientRequest} req Request object
46
+ * @param {IncomingMessage} res Response object
47
+ * @param {object} options Config object passed to the proxy
48
+ *
49
+ * @api private
50
+ */
51
+ XHeaders: function XHeaders(req, res, options) {
52
+ if (!options.xfwd)
53
+ return;
54
+ const encrypted = req.isSpdy || common.hasEncryptedConnection(req);
55
+ const values = {
56
+ for: req.connection.remoteAddress || req.socket.remoteAddress,
57
+ port: common.getPort(req),
58
+ proto: encrypted ? 'https' : 'http',
59
+ };
60
+ ['for', 'port', 'proto'].forEach(function (header) {
61
+ req.headers['x-forwarded-' + header] =
62
+ (req.headers['x-forwarded-' + header] || '') +
63
+ (req.headers['x-forwarded-' + header] ? ',' : '') +
64
+ values[header];
65
+ });
66
+ req.headers['x-forwarded-host'] =
67
+ req.headers['x-forwarded-host'] || req.headers['host'] || '';
68
+ },
69
+ /**
70
+ * Does the actual proxying. If `forward` is enabled fires up
71
+ * a ForwardStream, same happens for ProxyStream. The request
72
+ * just dies otherwise.
73
+ *
74
+ * @param {ClientRequest} req Request object
75
+ * @param {IncomingMessage} res Response object
76
+ * @param {object} options Config object passed to the proxy
77
+ *
78
+ * @api private
79
+ */
80
+ stream: function stream(req, res, options, _, server, clb) {
81
+ // And we begin!
82
+ server.emit('start', req, res, options.target || options.forward);
83
+ const agents = options.followRedirects ? followRedirects : nativeAgents;
84
+ const http = agents.http;
85
+ const https = agents.https;
86
+ if (options.forward) {
87
+ // If forward enable, so just pipe the request
88
+ const forwardReq = (options.forward.protocol === 'https:' ? https : http).request(common.setupOutgoing(options.ssl || {}, options, req, 'forward'));
89
+ // error handler (e.g. ECONNRESET, ECONNREFUSED)
90
+ // Handle errors on incoming request as well as it makes sense to
91
+ const forwardError = createErrorHandler(forwardReq, options.forward);
92
+ req.on('error', forwardError);
93
+ forwardReq.on('error', forwardError);
94
+ (options.buffer || req).pipe(forwardReq);
95
+ if (!options.target) {
96
+ return res.end();
97
+ }
98
+ }
99
+ // Request initalization
100
+ const proxyReq = (options.target.protocol === 'https:' ? https : http).request(common.setupOutgoing(options.ssl || {}, options, req));
101
+ // Enable developers to modify the proxyReq before headers are sent
102
+ proxyReq.on('socket', function (socket) {
103
+ if (server && !proxyReq.getHeader('expect')) {
104
+ server.emit('proxyReq', proxyReq, req, res, options);
105
+ }
106
+ });
107
+ // allow outgoing socket to timeout so that we could
108
+ // show an error page at the initial request
109
+ if (options.proxyTimeout) {
110
+ proxyReq.setTimeout(options.proxyTimeout, function () {
111
+ proxyReq.destroy();
112
+ });
113
+ }
114
+ // Ensure we abort proxy if request is aborted
115
+ // Need to use different methods due to node changes in 15.0.0.
116
+ // In node < 15.0.0, listen for request abort and destroy the proxy request.
117
+ req.on('aborted', function () {
118
+ proxyReq.destroy();
119
+ });
120
+ // In node > 15.0.0, listen for the close event on the response. If it was
121
+ // destroyed then destroy the proxy request.
122
+ res.on('close', function () {
123
+ if (res.destroyed) {
124
+ proxyReq.destroy();
125
+ }
126
+ });
127
+ // handle errors in proxy and incoming request, just like for forward proxy
128
+ const proxyError = createErrorHandler(proxyReq, options.target);
129
+ req.on('error', proxyError);
130
+ proxyReq.on('error', proxyError);
131
+ function createErrorHandler(proxyReq, url) {
132
+ return function proxyError(err) {
133
+ if (req.socket.destroyed && err.code === 'ECONNRESET') {
134
+ server.emit('econnreset', err, req, res, url);
135
+ proxyReq.destroy();
136
+ return;
137
+ }
138
+ if (clb) {
139
+ clb(err, req, res, url);
140
+ }
141
+ else {
142
+ server.emit('error', err, req, res, url);
143
+ }
144
+ };
145
+ }
146
+ (options.buffer || req).pipe(proxyReq);
147
+ proxyReq.on('response', function (proxyRes) {
148
+ if (server) {
149
+ server.emit('proxyRes', proxyRes, req, res);
150
+ }
151
+ if (!res.headersSent && !options.selfHandleResponse) {
152
+ for (let i = 0; i < web_o.length; i++) {
153
+ if (web_o[i](req, res, proxyRes, options)) {
154
+ break;
155
+ }
156
+ }
157
+ }
158
+ if (!res.finished) {
159
+ // Allow us to listen when the proxy has completed
160
+ proxyRes.on('end', function () {
161
+ if (server)
162
+ server.emit('end', req, res, proxyRes);
163
+ });
164
+ // We pipe to the response unless its expected to be handled by the user
165
+ if (!options.selfHandleResponse)
166
+ proxyRes.pipe(res);
167
+ }
168
+ else {
169
+ if (server)
170
+ server.emit('end', req, res, proxyRes);
171
+ }
172
+ });
173
+ },
174
+ };