proxy_chain_rb 0.1.0
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.
- checksums.yaml +7 -0
- data/.gitignore +14 -0
- data/.rspec +3 -0
- data/.travis.yml +7 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +41 -0
- data/LICENSE.txt +21 -0
- data/README.md +43 -0
- data/Rakefile +6 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/lib/proxy_chain_rb.rb +7 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/.bin/portastic +1 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/bluebird/LICENSE +21 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/bluebird/README.md +57 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/bluebird/changelog.md +1 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/bluebird/js/browser/bluebird.core.js +3824 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/bluebird/js/browser/bluebird.core.min.js +31 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/bluebird/js/browser/bluebird.js +5666 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/bluebird/js/browser/bluebird.min.js +31 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/bluebird/js/release/any.js +21 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/bluebird/js/release/assert.js +55 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/bluebird/js/release/async.js +165 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/bluebird/js/release/bind.js +67 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/bluebird/js/release/bluebird.js +11 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/bluebird/js/release/call_get.js +123 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/bluebird/js/release/cancel.js +129 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/bluebird/js/release/catch_filter.js +42 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/bluebird/js/release/context.js +69 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/bluebird/js/release/debuggability.js +934 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/bluebird/js/release/direct_resolve.js +46 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/bluebird/js/release/each.js +30 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/bluebird/js/release/errors.js +116 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/bluebird/js/release/es5.js +80 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/bluebird/js/release/filter.js +12 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/bluebird/js/release/finally.js +146 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/bluebird/js/release/generators.js +223 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/bluebird/js/release/join.js +168 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/bluebird/js/release/map.js +168 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/bluebird/js/release/method.js +55 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/bluebird/js/release/nodeback.js +51 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/bluebird/js/release/nodeify.js +58 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/bluebird/js/release/promise.js +789 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/bluebird/js/release/promise_array.js +185 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/bluebird/js/release/promisify.js +314 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/bluebird/js/release/props.js +118 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/bluebird/js/release/queue.js +73 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/bluebird/js/release/race.js +49 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/bluebird/js/release/reduce.js +172 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/bluebird/js/release/schedule.js +62 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/bluebird/js/release/settle.js +43 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/bluebird/js/release/some.js +148 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/bluebird/js/release/synchronous_inspection.js +103 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/bluebird/js/release/thenables.js +86 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/bluebird/js/release/timers.js +93 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/bluebird/js/release/using.js +226 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/bluebird/js/release/util.js +389 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/bluebird/package.json +102 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/commander/CHANGELOG.md +408 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/commander/LICENSE +22 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/commander/Readme.md +428 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/commander/index.js +1224 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/commander/package.json +70 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/commander/typings/index.d.ts +310 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/debug/.coveralls.yml +1 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/debug/.eslintrc +11 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/debug/.npmignore +9 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/debug/.travis.yml +14 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/debug/CHANGELOG.md +362 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/debug/LICENSE +19 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/debug/Makefile +50 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/debug/README.md +312 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/debug/component.json +19 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/debug/karma.conf.js +70 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/debug/node.js +1 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/debug/package.json +88 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/debug/src/browser.js +185 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/debug/src/debug.js +202 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/debug/src/index.js +10 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/debug/src/inspector-log.js +15 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/debug/src/node.js +248 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/ms/index.js +152 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/ms/license.md +21 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/ms/package.json +69 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/ms/readme.md +51 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/portastic/LICENSE +13 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/portastic/README.md +148 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/portastic/bin/portastic +65 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/portastic/history.md +7 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/portastic/index.js +4 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/portastic/lib/monitor.js +59 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/portastic/lib/portastic.js +167 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/portastic/node_modules/bluebird/LICENSE +21 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/portastic/node_modules/bluebird/README.md +677 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/portastic/node_modules/bluebird/changelog.md +1730 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/portastic/node_modules/bluebird/js/browser/bluebird.js +4892 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/portastic/node_modules/bluebird/js/browser/bluebird.min.js +31 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/portastic/node_modules/bluebird/js/main/any.js +21 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/portastic/node_modules/bluebird/js/main/assert.js +55 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/portastic/node_modules/bluebird/js/main/async.js +150 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/portastic/node_modules/bluebird/js/main/bind.js +72 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/portastic/node_modules/bluebird/js/main/bluebird.js +11 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/portastic/node_modules/bluebird/js/main/call_get.js +123 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/portastic/node_modules/bluebird/js/main/cancel.js +48 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/portastic/node_modules/bluebird/js/main/captured_trace.js +493 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/portastic/node_modules/bluebird/js/main/catch_filter.js +66 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/portastic/node_modules/bluebird/js/main/context.js +38 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/portastic/node_modules/bluebird/js/main/debuggability.js +162 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/portastic/node_modules/bluebird/js/main/direct_resolve.js +63 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/portastic/node_modules/bluebird/js/main/each.js +12 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/portastic/node_modules/bluebird/js/main/errors.js +111 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/portastic/node_modules/bluebird/js/main/es5.js +80 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/portastic/node_modules/bluebird/js/main/filter.js +12 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/portastic/node_modules/bluebird/js/main/finally.js +98 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/portastic/node_modules/bluebird/js/main/generators.js +136 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/portastic/node_modules/bluebird/js/main/join.js +107 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/portastic/node_modules/bluebird/js/main/map.js +133 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/portastic/node_modules/bluebird/js/main/method.js +44 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/portastic/node_modules/bluebird/js/main/nodeify.js +59 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/portastic/node_modules/bluebird/js/main/progress.js +76 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/portastic/node_modules/bluebird/js/main/promise.js +759 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/portastic/node_modules/bluebird/js/main/promise_array.js +142 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/portastic/node_modules/bluebird/js/main/promise_resolver.js +123 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/portastic/node_modules/bluebird/js/main/promisify.js +307 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/portastic/node_modules/bluebird/js/main/props.js +79 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/portastic/node_modules/bluebird/js/main/queue.js +90 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/portastic/node_modules/bluebird/js/main/race.js +47 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/portastic/node_modules/bluebird/js/main/reduce.js +148 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/portastic/node_modules/bluebird/js/main/schedule.js +35 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/portastic/node_modules/bluebird/js/main/settle.js +40 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/portastic/node_modules/bluebird/js/main/some.js +125 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/portastic/node_modules/bluebird/js/main/synchronous_inspection.js +94 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/portastic/node_modules/bluebird/js/main/thenables.js +84 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/portastic/node_modules/bluebird/js/main/timers.js +64 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/portastic/node_modules/bluebird/js/main/using.js +213 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/portastic/node_modules/bluebird/js/main/util.js +321 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/portastic/node_modules/bluebird/package.json +103 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/portastic/package.json +69 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/proxy-chain/CHANGELOG.md +109 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/proxy-chain/LICENSE +201 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/proxy-chain/README.md +278 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/proxy-chain/build/anonymize_proxy.js +100 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/proxy-chain/build/handler_base.js +319 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/proxy-chain/build/handler_custom_response.js +96 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/proxy-chain/build/handler_forward.js +173 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/proxy-chain/build/handler_tunnel_chain.js +132 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/proxy-chain/build/handler_tunnel_direct.js +89 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/proxy-chain/build/handler_tunnel_tcp_chain.js +271 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/proxy-chain/build/index.js +26 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/proxy-chain/build/run_locally.js +66 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/proxy-chain/build/server.js +595 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/proxy-chain/build/tcp_tunnel.js +138 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/proxy-chain/build/testing_tcp_service.js +37 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/proxy-chain/build/tools.js +220 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/proxy-chain/package.json +104 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/underscore/LICENSE +23 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/underscore/README.md +28 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/underscore/package.json +81 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/underscore/underscore-min.js +5 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/underscore/underscore-min.js.map +1 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/underscore/underscore.js +1692 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/package-lock.json +63 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/package.json +15 -0
- data/lib/proxy_chain_rb/node_js/proxy-chain-server/server.js +25 -0
- data/lib/proxy_chain_rb/server.rb +49 -0
- data/lib/proxy_chain_rb/version.rb +3 -0
- data/proxy_chain_rb.gemspec +31 -0
- metadata +266 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var _server = require('./server');
|
|
4
|
+
|
|
5
|
+
var _tools = require('./tools');
|
|
6
|
+
|
|
7
|
+
var _anonymize_proxy = require('./anonymize_proxy');
|
|
8
|
+
|
|
9
|
+
var _tcp_tunnel = require('./tcp_tunnel');
|
|
10
|
+
|
|
11
|
+
/* globals module */
|
|
12
|
+
|
|
13
|
+
// Publicly exported functions and classes
|
|
14
|
+
var ProxyChain = {
|
|
15
|
+
Server: _server.Server,
|
|
16
|
+
RequestError: _server.RequestError,
|
|
17
|
+
parseUrl: _tools.parseUrl,
|
|
18
|
+
redactUrl: _tools.redactUrl,
|
|
19
|
+
redactParsedUrl: _tools.redactParsedUrl,
|
|
20
|
+
anonymizeProxy: _anonymize_proxy.anonymizeProxy,
|
|
21
|
+
closeAnonymizedProxy: _anonymize_proxy.closeAnonymizedProxy,
|
|
22
|
+
createTunnel: _tcp_tunnel.createTunnel,
|
|
23
|
+
closeTunnel: _tcp_tunnel.closeTunnel
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
module.exports = ProxyChain;
|
data/lib/proxy_chain_rb/node_js/proxy-chain-server/node_modules/proxy-chain/build/run_locally.js
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var _http = require('http');
|
|
4
|
+
|
|
5
|
+
var _http2 = _interopRequireDefault(_http);
|
|
6
|
+
|
|
7
|
+
var _proxy = require('proxy');
|
|
8
|
+
|
|
9
|
+
var _proxy2 = _interopRequireDefault(_proxy);
|
|
10
|
+
|
|
11
|
+
var _server = require('./server');
|
|
12
|
+
|
|
13
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
14
|
+
|
|
15
|
+
// Set up upstream proxy with no auth
|
|
16
|
+
var upstreamProxyHttpServer = _http2.default.createServer(); // eslint-disable-line import/no-extraneous-dependencies
|
|
17
|
+
/*!
|
|
18
|
+
* This script runs the proxy with a second upstream proxy locally on port specified by PORT environment variable
|
|
19
|
+
* or 8080 if not provided. This is used to manually test the proxy on normal browsing.
|
|
20
|
+
*
|
|
21
|
+
* node ./build/run_locally.js
|
|
22
|
+
*
|
|
23
|
+
* Author: Jan Curn (jan@apify.com)
|
|
24
|
+
* Copyright(c) 2017 Apify Technologies. All rights reserved.
|
|
25
|
+
*
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
upstreamProxyHttpServer.on('error', function (err) {
|
|
29
|
+
console.error(err.stack || err);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
var upstreamProxyServer = (0, _proxy2.default)(upstreamProxyHttpServer);
|
|
33
|
+
var upstreamProxyPort = process.env.UPSTREAM_PROXY_PORT || 8081;
|
|
34
|
+
upstreamProxyServer.listen(process.env.UPSTREAM_PROXY_PORT || 8081, function (err) {
|
|
35
|
+
if (err) {
|
|
36
|
+
console.error(err.stack || err);
|
|
37
|
+
process.exit(1);
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
// Setup proxy to forward to upstream
|
|
42
|
+
var server = new _server.Server({
|
|
43
|
+
port: process.env.PORT || 8080,
|
|
44
|
+
// verbose: true,
|
|
45
|
+
prepareRequestFunction: function prepareRequestFunction() {
|
|
46
|
+
return { requestAuthentication: false, upstreamProxyUrl: 'http://127.0.0.1:' + upstreamProxyPort };
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
server.on('requestFailed', function (_ref) {
|
|
51
|
+
var error = _ref.error,
|
|
52
|
+
request = _ref.request;
|
|
53
|
+
|
|
54
|
+
console.error('Request failed (' + (request ? request.url : 'N/A') + '): ' + (error.stack || error));
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
server.listen().then(function () {
|
|
58
|
+
console.log('Proxy server is running at http://127.0.0.1:' + server.port);
|
|
59
|
+
|
|
60
|
+
setInterval(function () {
|
|
61
|
+
console.log('Stats: ' + JSON.stringify(server.stats));
|
|
62
|
+
}, 30000);
|
|
63
|
+
}).catch(function (err) {
|
|
64
|
+
console.error(err.stack || err);
|
|
65
|
+
process.exit(1);
|
|
66
|
+
});
|
|
@@ -0,0 +1,595 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.Server = exports.RequestError = undefined;
|
|
7
|
+
|
|
8
|
+
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
|
|
9
|
+
|
|
10
|
+
var _http = require('http');
|
|
11
|
+
|
|
12
|
+
var _http2 = _interopRequireDefault(_http);
|
|
13
|
+
|
|
14
|
+
var _events = require('events');
|
|
15
|
+
|
|
16
|
+
var _events2 = _interopRequireDefault(_events);
|
|
17
|
+
|
|
18
|
+
var _underscore = require('underscore');
|
|
19
|
+
|
|
20
|
+
var _underscore2 = _interopRequireDefault(_underscore);
|
|
21
|
+
|
|
22
|
+
var _bluebird = require('bluebird');
|
|
23
|
+
|
|
24
|
+
var _bluebird2 = _interopRequireDefault(_bluebird);
|
|
25
|
+
|
|
26
|
+
var _tools = require('./tools');
|
|
27
|
+
|
|
28
|
+
var _handler_forward = require('./handler_forward');
|
|
29
|
+
|
|
30
|
+
var _handler_forward2 = _interopRequireDefault(_handler_forward);
|
|
31
|
+
|
|
32
|
+
var _handler_tunnel_direct = require('./handler_tunnel_direct');
|
|
33
|
+
|
|
34
|
+
var _handler_tunnel_direct2 = _interopRequireDefault(_handler_tunnel_direct);
|
|
35
|
+
|
|
36
|
+
var _handler_tunnel_chain = require('./handler_tunnel_chain');
|
|
37
|
+
|
|
38
|
+
var _handler_tunnel_chain2 = _interopRequireDefault(_handler_tunnel_chain);
|
|
39
|
+
|
|
40
|
+
var _handler_custom_response = require('./handler_custom_response');
|
|
41
|
+
|
|
42
|
+
var _handler_custom_response2 = _interopRequireDefault(_handler_custom_response);
|
|
43
|
+
|
|
44
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
45
|
+
|
|
46
|
+
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
|
47
|
+
|
|
48
|
+
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
|
|
49
|
+
|
|
50
|
+
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
|
|
51
|
+
|
|
52
|
+
// TODO:
|
|
53
|
+
// - Fail gracefully if target proxy fails (invalid credentials or non-existent)
|
|
54
|
+
// - Implement this requirement from rfc7230
|
|
55
|
+
// "A proxy MUST forward unrecognized header fields unless the field-name
|
|
56
|
+
// is listed in the Connection header field (Section 6.1) or the proxy
|
|
57
|
+
// is specifically configured to block, or otherwise transform, such
|
|
58
|
+
// fields. Other recipients SHOULD ignore unrecognized header fields.
|
|
59
|
+
// These requirements allow HTTP's functionality to be enhanced without
|
|
60
|
+
// requiring prior update of deployed intermediaries."
|
|
61
|
+
// - Add param to prepareRequestFunction() that would allow the caller to kill a connection
|
|
62
|
+
|
|
63
|
+
// TODO:
|
|
64
|
+
// - Use connection pooling and maybe other stuff from:
|
|
65
|
+
// https://github.com/request/tunnel-agent/blob/master/index.js
|
|
66
|
+
// https://github.com/request/request/blob/master/lib/tunnel.js
|
|
67
|
+
|
|
68
|
+
var DEFAULT_AUTH_REALM = 'ProxyChain';
|
|
69
|
+
var DEFAULT_PROXY_SERVER_PORT = 8000;
|
|
70
|
+
var DEFAULT_TARGET_PORT = 80;
|
|
71
|
+
|
|
72
|
+
var REQUEST_ERROR_NAME = 'RequestError';
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Represents custom request error. The message is emitted as HTTP response
|
|
76
|
+
* with a specific HTTP code and headers.
|
|
77
|
+
* If this error is thrown from the `prepareRequestFunction` function,
|
|
78
|
+
* the message and status code is sent to client.
|
|
79
|
+
* By default, the response will have Content-Type: text/plain
|
|
80
|
+
* and for the 407 status the Proxy-Authenticate header will be added.
|
|
81
|
+
*/
|
|
82
|
+
|
|
83
|
+
var RequestError = exports.RequestError = function (_Error) {
|
|
84
|
+
_inherits(RequestError, _Error);
|
|
85
|
+
|
|
86
|
+
function RequestError(message, statusCode, headers) {
|
|
87
|
+
_classCallCheck(this, RequestError);
|
|
88
|
+
|
|
89
|
+
var _this = _possibleConstructorReturn(this, (RequestError.__proto__ || Object.getPrototypeOf(RequestError)).call(this, message));
|
|
90
|
+
|
|
91
|
+
_this.name = REQUEST_ERROR_NAME;
|
|
92
|
+
_this.statusCode = statusCode;
|
|
93
|
+
_this.headers = headers;
|
|
94
|
+
|
|
95
|
+
Error.captureStackTrace(_this, RequestError);
|
|
96
|
+
return _this;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return RequestError;
|
|
100
|
+
}(Error);
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Represents the proxy server.
|
|
104
|
+
* It emits the 'requestFailed' event on unexpected request errors, with the following parameter `{ error, request }`.
|
|
105
|
+
* It emits the 'connectionClosed' event when connection to proxy server is closed, with parameter `{ connectionId, stats }`.
|
|
106
|
+
*/
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
var Server = exports.Server = function (_EventEmitter) {
|
|
110
|
+
_inherits(Server, _EventEmitter);
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Initializes a new instance of Server class.
|
|
114
|
+
* @param options
|
|
115
|
+
* @param [options.port] Port where the server will listen. By default 8000.
|
|
116
|
+
* @param [options.prepareRequestFunction] Custom function to authenticate proxy requests,
|
|
117
|
+
* provide URL to chained upstream proxy or potentially provide function that generates a custom response to HTTP requests.
|
|
118
|
+
* It accepts a single parameter which is an object:
|
|
119
|
+
* ```{
|
|
120
|
+
* connectionId: Number,
|
|
121
|
+
* request: Object,
|
|
122
|
+
* username: String,
|
|
123
|
+
* password: String,
|
|
124
|
+
* hostname: String,
|
|
125
|
+
* port: Number,
|
|
126
|
+
* isHttp: Boolean
|
|
127
|
+
* }```
|
|
128
|
+
* and returns an object (or promise resolving to the object) with following form:
|
|
129
|
+
* ```{
|
|
130
|
+
* requestAuthentication: Boolean,
|
|
131
|
+
* upstreamProxyUrl: String,
|
|
132
|
+
* customResponseFunction: Function
|
|
133
|
+
* }```
|
|
134
|
+
* If `upstreamProxyUrl` is false-ish value, no upstream proxy is used.
|
|
135
|
+
* If `prepareRequestFunction` is not set, the proxy server will not require any authentication
|
|
136
|
+
* and will not use any upstream proxy.
|
|
137
|
+
* If `customResponseFunction` is set, it will be called to generate a custom response to the HTTP request.
|
|
138
|
+
* It should not be used together with `upstreamProxyUrl`.
|
|
139
|
+
* @param [options.authRealm] Realm used in the Proxy-Authenticate header and also in the 'Server' HTTP header. By default it's `ProxyChain`.
|
|
140
|
+
* @param [options.verbose] If true, the server logs
|
|
141
|
+
*/
|
|
142
|
+
function Server(options) {
|
|
143
|
+
_classCallCheck(this, Server);
|
|
144
|
+
|
|
145
|
+
var _this2 = _possibleConstructorReturn(this, (Server.__proto__ || Object.getPrototypeOf(Server)).call(this));
|
|
146
|
+
|
|
147
|
+
options = options || {};
|
|
148
|
+
|
|
149
|
+
_this2.port = options.port || DEFAULT_PROXY_SERVER_PORT;
|
|
150
|
+
_this2.prepareRequestFunction = options.prepareRequestFunction;
|
|
151
|
+
_this2.authRealm = options.authRealm || DEFAULT_AUTH_REALM;
|
|
152
|
+
_this2.verbose = !!options.verbose;
|
|
153
|
+
|
|
154
|
+
// Key is handler ID, value is HandlerXxx instance
|
|
155
|
+
_this2.handlers = {};
|
|
156
|
+
_this2.lastHandlerId = 0;
|
|
157
|
+
|
|
158
|
+
_this2.server = _http2.default.createServer();
|
|
159
|
+
_this2.server.on('clientError', _this2.onClientError.bind(_this2));
|
|
160
|
+
_this2.server.on('request', _this2.onRequest.bind(_this2));
|
|
161
|
+
_this2.server.on('connect', _this2.onConnect.bind(_this2));
|
|
162
|
+
|
|
163
|
+
_this2.stats = {
|
|
164
|
+
httpRequestCount: 0,
|
|
165
|
+
connectRequestCount: 0
|
|
166
|
+
};
|
|
167
|
+
return _this2;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
_createClass(Server, [{
|
|
171
|
+
key: 'log',
|
|
172
|
+
value: function log(handlerId, str) {
|
|
173
|
+
if (this.verbose) {
|
|
174
|
+
var logPrefix = handlerId ? handlerId + ' | ' : '';
|
|
175
|
+
console.log('Server[' + this.port + ']: ' + logPrefix + str);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}, {
|
|
179
|
+
key: 'onClientError',
|
|
180
|
+
value: function onClientError(err, socket) {
|
|
181
|
+
this.log(null, 'onClientError: ' + err);
|
|
182
|
+
this.sendResponse(socket, 400, null, 'Invalid request');
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Handles normal HTTP request by forwarding it to target host or the upstream proxy.
|
|
187
|
+
*/
|
|
188
|
+
|
|
189
|
+
}, {
|
|
190
|
+
key: 'onRequest',
|
|
191
|
+
value: function onRequest(request, response) {
|
|
192
|
+
var _this3 = this;
|
|
193
|
+
|
|
194
|
+
var handlerOpts = void 0;
|
|
195
|
+
this.prepareRequestHandling(request).then(function (result) {
|
|
196
|
+
handlerOpts = result;
|
|
197
|
+
handlerOpts.srcResponse = response;
|
|
198
|
+
|
|
199
|
+
var handler = void 0;
|
|
200
|
+
if (handlerOpts.customResponseFunction) {
|
|
201
|
+
_this3.log(handlerOpts.id, 'Using HandlerCustomResponse');
|
|
202
|
+
handler = new _handler_custom_response2.default(handlerOpts);
|
|
203
|
+
} else {
|
|
204
|
+
_this3.log(handlerOpts.id, 'Using HandlerForward');
|
|
205
|
+
handler = new _handler_forward2.default(handlerOpts);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
_this3.handlerRun(handler);
|
|
209
|
+
}).catch(function (err) {
|
|
210
|
+
_this3.failRequest(request, err, handlerOpts);
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Handles HTTP CONNECT request by setting up a tunnel either to target host or to the upstream proxy.
|
|
216
|
+
* @param request
|
|
217
|
+
* @param socket
|
|
218
|
+
* @param head The first packet of the tunneling stream (may be empty)
|
|
219
|
+
*/
|
|
220
|
+
|
|
221
|
+
}, {
|
|
222
|
+
key: 'onConnect',
|
|
223
|
+
value: function onConnect(request, socket, head) {
|
|
224
|
+
var _this4 = this;
|
|
225
|
+
|
|
226
|
+
var handlerOpts = void 0;
|
|
227
|
+
this.prepareRequestHandling(request).then(function (result) {
|
|
228
|
+
handlerOpts = result;
|
|
229
|
+
handlerOpts.srcHead = head;
|
|
230
|
+
|
|
231
|
+
var handler = void 0;
|
|
232
|
+
if (handlerOpts.upstreamProxyUrlParsed) {
|
|
233
|
+
_this4.log(handlerOpts.id, 'Using HandlerTunnelChain');
|
|
234
|
+
handler = new _handler_tunnel_chain2.default(handlerOpts);
|
|
235
|
+
} else {
|
|
236
|
+
_this4.log(handlerOpts.id, 'Using HandlerTunnelDirect');
|
|
237
|
+
handler = new _handler_tunnel_direct2.default(handlerOpts);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
_this4.handlerRun(handler);
|
|
241
|
+
}).catch(function (err) {
|
|
242
|
+
_this4.failRequest(request, err, handlerOpts);
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Authenticates a new request and determines upstream proxy URL using the user function.
|
|
248
|
+
* Returns a promise resolving to an object that can be passed to construcot of one of the HandlerXxx classes.
|
|
249
|
+
* @param request
|
|
250
|
+
*/
|
|
251
|
+
|
|
252
|
+
}, {
|
|
253
|
+
key: 'prepareRequestHandling',
|
|
254
|
+
value: function prepareRequestHandling(request) {
|
|
255
|
+
var _this5 = this;
|
|
256
|
+
|
|
257
|
+
// console.log('XXX prepareRequestHandling');
|
|
258
|
+
// console.dir(_.pick(request, 'url', 'method'));
|
|
259
|
+
// console.dir(url.parse(request.url));
|
|
260
|
+
|
|
261
|
+
var handlerOpts = {
|
|
262
|
+
server: this,
|
|
263
|
+
id: ++this.lastHandlerId,
|
|
264
|
+
srcRequest: request,
|
|
265
|
+
srcHead: null,
|
|
266
|
+
trgParsed: null,
|
|
267
|
+
upstreamProxyUrlParsed: null
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
this.log(handlerOpts.id, '!!! Handling ' + request.method + ' ' + request.url + ' HTTP/' + request.httpVersion);
|
|
271
|
+
|
|
272
|
+
var socket = request.socket;
|
|
273
|
+
var isHttp = false;
|
|
274
|
+
|
|
275
|
+
return _bluebird2.default.resolve().then(function () {
|
|
276
|
+
// console.dir(_.pick(request, 'url', 'headers', 'method'));
|
|
277
|
+
// Determine target hostname and port
|
|
278
|
+
if (request.method === 'CONNECT') {
|
|
279
|
+
// The request should look like:
|
|
280
|
+
// CONNECT server.example.com:80 HTTP/1.1
|
|
281
|
+
// Note that request.url contains the "server.example.com:80" part
|
|
282
|
+
handlerOpts.trgParsed = (0, _tools.parseHostHeader)(request.url);
|
|
283
|
+
|
|
284
|
+
// If srcRequest.url does not match the regexp tools.HOST_HEADER_REGEX
|
|
285
|
+
// or the url is too long it will not be parsed so we throw error here.
|
|
286
|
+
if (!handlerOpts.trgParsed) {
|
|
287
|
+
throw new RequestError('Target "' + request.url + '" could not be parsed', 400);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
_this5.stats.connectRequestCount++;
|
|
291
|
+
} else {
|
|
292
|
+
// The request should look like:
|
|
293
|
+
// GET http://server.example.com:80/some-path HTTP/1.1
|
|
294
|
+
// Note that RFC 7230 says:
|
|
295
|
+
// "When making a request to a proxy, other than a CONNECT or server-wide
|
|
296
|
+
// OPTIONS request (as detailed below), a client MUST send the target
|
|
297
|
+
// URI in absolute-form as the request-target"
|
|
298
|
+
var parsed = (0, _tools.parseUrl)(request.url);
|
|
299
|
+
|
|
300
|
+
// If srcRequest.url does not match the regexp tools.HOST_HEADER_REGEX
|
|
301
|
+
// or the url is too long it will not be parsed so we throw error here.
|
|
302
|
+
if (!parsed) {
|
|
303
|
+
throw new RequestError('Target "' + request.url + '" could not be parsed', 400);
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// If srcRequest.url is something like '/some-path', this is most likely a normal HTTP request
|
|
307
|
+
if (!parsed.protocol) {
|
|
308
|
+
throw new RequestError('Hey, good try, but I\'m a HTTP proxy, not your ordinary web server :)', 400);
|
|
309
|
+
}
|
|
310
|
+
// Only HTTP is supported, other protocols such as HTTP or FTP must use the CONNECT method
|
|
311
|
+
if (parsed.protocol !== 'http:') {
|
|
312
|
+
throw new RequestError('Only HTTP protocol is supported (was ' + parsed.protocol + ')', 400);
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
handlerOpts.trgParsed = parsed;
|
|
316
|
+
isHttp = true;
|
|
317
|
+
|
|
318
|
+
_this5.stats.httpRequestCount++;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
handlerOpts.trgParsed.port = handlerOpts.trgParsed.port || DEFAULT_TARGET_PORT;
|
|
322
|
+
|
|
323
|
+
// Authenticate the request using a user function (if provided)
|
|
324
|
+
if (!_this5.prepareRequestFunction) return { requestAuthentication: false, upstreamProxyUrlParsed: null };
|
|
325
|
+
|
|
326
|
+
// Pause the socket so that no data is lost
|
|
327
|
+
socket.pause();
|
|
328
|
+
|
|
329
|
+
var funcOpts = {
|
|
330
|
+
connectionId: handlerOpts.id,
|
|
331
|
+
request: request,
|
|
332
|
+
username: null,
|
|
333
|
+
password: null,
|
|
334
|
+
hostname: handlerOpts.trgParsed.hostname,
|
|
335
|
+
port: handlerOpts.trgParsed.port,
|
|
336
|
+
isHttp: isHttp
|
|
337
|
+
};
|
|
338
|
+
|
|
339
|
+
var proxyAuth = request.headers['proxy-authorization'];
|
|
340
|
+
if (proxyAuth) {
|
|
341
|
+
var auth = (0, _tools.parseProxyAuthorizationHeader)(proxyAuth);
|
|
342
|
+
if (!auth) {
|
|
343
|
+
throw new RequestError('Invalid "Proxy-Authorization" header', 400);
|
|
344
|
+
}
|
|
345
|
+
if (auth.type !== 'Basic') {
|
|
346
|
+
throw new RequestError('The "Proxy-Authorization" header must have the "Basic" type.', 400);
|
|
347
|
+
}
|
|
348
|
+
funcOpts.username = auth.username;
|
|
349
|
+
funcOpts.password = auth.password;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
// User function returns a result directly or a promise
|
|
353
|
+
return _this5.prepareRequestFunction(funcOpts);
|
|
354
|
+
}).then(function (funcResult) {
|
|
355
|
+
// If not authenticated, request client to authenticate
|
|
356
|
+
if (funcResult && funcResult.requestAuthentication) {
|
|
357
|
+
throw new RequestError(funcResult.failMsg || 'Proxy credentials required.', 407);
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
if (funcResult && funcResult.upstreamProxyUrl) {
|
|
361
|
+
handlerOpts.upstreamProxyUrlParsed = (0, _tools.parseUrl)(funcResult.upstreamProxyUrl);
|
|
362
|
+
|
|
363
|
+
if (handlerOpts.upstreamProxyUrlParsed) {
|
|
364
|
+
if (!handlerOpts.upstreamProxyUrlParsed.hostname || !handlerOpts.upstreamProxyUrlParsed.port) {
|
|
365
|
+
throw new Error('Invalid "upstreamProxyUrl" provided: URL must have hostname and port');
|
|
366
|
+
}
|
|
367
|
+
if (handlerOpts.upstreamProxyUrlParsed.scheme !== 'http') {
|
|
368
|
+
throw new Error('Invalid "upstreamProxyUrl" provided: URL must have the "http" scheme');
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
if (funcResult && funcResult.customResponseFunction) {
|
|
374
|
+
_this5.log(handlerOpts.id, 'Using custom response function');
|
|
375
|
+
handlerOpts.customResponseFunction = funcResult.customResponseFunction;
|
|
376
|
+
if (!isHttp) {
|
|
377
|
+
throw new Error('The "customResponseFunction" option can only be used for HTTP requests.');
|
|
378
|
+
}
|
|
379
|
+
if (typeof handlerOpts.customResponseFunction !== 'function') {
|
|
380
|
+
throw new Error('The "customResponseFunction" option must be a function.');
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
if (handlerOpts.upstreamProxyUrlParsed) {
|
|
385
|
+
_this5.log(handlerOpts.id, 'Using upstream proxy ' + (0, _tools.redactParsedUrl)(handlerOpts.upstreamProxyUrlParsed));
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
return handlerOpts;
|
|
389
|
+
}).finally(function () {
|
|
390
|
+
if (_this5.prepareRequestFunction) socket.resume();
|
|
391
|
+
});
|
|
392
|
+
}
|
|
393
|
+
}, {
|
|
394
|
+
key: 'handlerRun',
|
|
395
|
+
value: function handlerRun(handler) {
|
|
396
|
+
var _this6 = this;
|
|
397
|
+
|
|
398
|
+
this.handlers[handler.id] = handler;
|
|
399
|
+
|
|
400
|
+
handler.once('close', function (_ref) {
|
|
401
|
+
var stats = _ref.stats;
|
|
402
|
+
|
|
403
|
+
_this6.emit('connectionClosed', {
|
|
404
|
+
connectionId: handler.id,
|
|
405
|
+
stats: stats
|
|
406
|
+
});
|
|
407
|
+
delete _this6.handlers[handler.id];
|
|
408
|
+
_this6.log(handler.id, '!!! Closed and removed from server');
|
|
409
|
+
});
|
|
410
|
+
|
|
411
|
+
handler.run();
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
/**
|
|
415
|
+
* Sends a HTTP error response to the client.
|
|
416
|
+
* @param request
|
|
417
|
+
* @param err
|
|
418
|
+
*/
|
|
419
|
+
|
|
420
|
+
}, {
|
|
421
|
+
key: 'failRequest',
|
|
422
|
+
value: function failRequest(request, err, handlerOpts) {
|
|
423
|
+
var handlerId = handlerOpts ? handlerOpts.id : null;
|
|
424
|
+
|
|
425
|
+
if (err.name === REQUEST_ERROR_NAME) {
|
|
426
|
+
this.log(handlerId, 'Request failed (status ' + err.statusCode + '): ' + err.message);
|
|
427
|
+
this.sendResponse(request.socket, err.statusCode, err.headers, err.message);
|
|
428
|
+
} else {
|
|
429
|
+
this.log(handlerId, 'Request failed with unknown error: ' + (err.stack || err));
|
|
430
|
+
this.sendResponse(request.socket, 500, null, 'Internal error in proxy server');
|
|
431
|
+
this.emit('requestFailed', { error: err, request: request });
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
// emit connection closed if request fails and connection was already reported
|
|
435
|
+
if (handlerOpts) {
|
|
436
|
+
this.log(handlerId, 'Closed because request failed with error');
|
|
437
|
+
this.emit('connectionClosed', {
|
|
438
|
+
connectionId: handlerOpts.id,
|
|
439
|
+
stats: { srcTxBytes: 0, srcRxBytes: 0 }
|
|
440
|
+
});
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
/**
|
|
445
|
+
* Sends a simple HTTP response to the client and forcibly closes the connection.
|
|
446
|
+
* @param socket
|
|
447
|
+
* @param statusCode
|
|
448
|
+
* @param headers
|
|
449
|
+
* @param message
|
|
450
|
+
*/
|
|
451
|
+
|
|
452
|
+
}, {
|
|
453
|
+
key: 'sendResponse',
|
|
454
|
+
value: function sendResponse(socket, statusCode, headers, message) {
|
|
455
|
+
try {
|
|
456
|
+
headers = headers || {};
|
|
457
|
+
|
|
458
|
+
if (!headers['Content-Type']) {
|
|
459
|
+
headers['Content-Type'] = 'text/html; charset=utf-8';
|
|
460
|
+
}
|
|
461
|
+
if (statusCode === 407 && !headers['Proxy-Authenticate']) {
|
|
462
|
+
headers['Proxy-Authenticate'] = 'Basic realm="' + this.authRealm + '"';
|
|
463
|
+
}
|
|
464
|
+
if (!headers.Server) {
|
|
465
|
+
headers.Server = this.authRealm;
|
|
466
|
+
}
|
|
467
|
+
// These headers are required by PhantomJS, otherwise the connection would timeout!
|
|
468
|
+
if (!headers.Connection) {
|
|
469
|
+
headers.Connection = 'close';
|
|
470
|
+
}
|
|
471
|
+
if (!headers['Content-Length']) {
|
|
472
|
+
headers['Content-Length'] = Buffer.byteLength(message);
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
var msg = 'HTTP/1.1 ' + statusCode + ' ' + _http2.default.STATUS_CODES[statusCode] + '\r\n';
|
|
476
|
+
_underscore2.default.each(headers, function (value, key) {
|
|
477
|
+
msg += key + ': ' + value + '\r\n';
|
|
478
|
+
});
|
|
479
|
+
msg += '\r\n' + message;
|
|
480
|
+
|
|
481
|
+
// console.log("RESPONSE:\n" + msg);
|
|
482
|
+
|
|
483
|
+
socket.write(msg, function () {
|
|
484
|
+
socket.end();
|
|
485
|
+
|
|
486
|
+
// Unfortunately calling end() will not close the socket
|
|
487
|
+
// if client refuses to close it. Hence calling destroy after a short while.
|
|
488
|
+
setTimeout(function () {
|
|
489
|
+
socket.destroy();
|
|
490
|
+
}, 100);
|
|
491
|
+
});
|
|
492
|
+
} catch (err) {
|
|
493
|
+
this.log(null, 'Unhandled error in sendResponse(), will be ignored: ' + (err.stack || err));
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
/**
|
|
498
|
+
* Starts listening at a port specified in the constructor.
|
|
499
|
+
* @param callback Optional callback
|
|
500
|
+
* @return {*}
|
|
501
|
+
*/
|
|
502
|
+
|
|
503
|
+
}, {
|
|
504
|
+
key: 'listen',
|
|
505
|
+
value: function listen(callback) {
|
|
506
|
+
var _this7 = this;
|
|
507
|
+
|
|
508
|
+
return new _bluebird2.default(function (resolve, reject) {
|
|
509
|
+
// Unfortunately server.listen() is not a normal function that fails on error,
|
|
510
|
+
// so we need this trickery
|
|
511
|
+
var onError = function onError(err) {
|
|
512
|
+
_this7.log(null, 'Listen failed: ' + err);
|
|
513
|
+
removeListeners();
|
|
514
|
+
reject(err);
|
|
515
|
+
};
|
|
516
|
+
var onListening = function onListening() {
|
|
517
|
+
_this7.log(null, 'Listening...');
|
|
518
|
+
removeListeners();
|
|
519
|
+
resolve();
|
|
520
|
+
};
|
|
521
|
+
var removeListeners = function removeListeners() {
|
|
522
|
+
_this7.server.removeListener('error', onError);
|
|
523
|
+
_this7.server.removeListener('listening', onListening);
|
|
524
|
+
};
|
|
525
|
+
|
|
526
|
+
_this7.server.on('error', onError);
|
|
527
|
+
_this7.server.on('listening', onListening);
|
|
528
|
+
_this7.server.listen(_this7.port);
|
|
529
|
+
}).nodeify(callback);
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
/**
|
|
533
|
+
* Gets array of IDs of all active connections.
|
|
534
|
+
* @returns {*}
|
|
535
|
+
*/
|
|
536
|
+
|
|
537
|
+
}, {
|
|
538
|
+
key: 'getConnectionIds',
|
|
539
|
+
value: function getConnectionIds() {
|
|
540
|
+
return _underscore2.default.keys(this.handlers);
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
/**
|
|
544
|
+
* Gets data transfer statistics of a specific proxy connection.
|
|
545
|
+
* @param {Number} connectionId ID of the connection handler.
|
|
546
|
+
* It is passed to `prepareRequestFunction` function.
|
|
547
|
+
* @return {Object} An object with statistics { srcTxBytes, srcRxBytes, trgTxBytes, trgRxBytes },
|
|
548
|
+
* or null if connection does not exist or has been closed.
|
|
549
|
+
*/
|
|
550
|
+
|
|
551
|
+
}, {
|
|
552
|
+
key: 'getConnectionStats',
|
|
553
|
+
value: function getConnectionStats(connectionId) {
|
|
554
|
+
var handler = this.handlers && this.handlers[connectionId];
|
|
555
|
+
if (!handler) return undefined;
|
|
556
|
+
|
|
557
|
+
return handler.getStats();
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
/**
|
|
561
|
+
* Closes the proxy server.
|
|
562
|
+
* @param [closeConnections] If true, then all the pending connections from clients
|
|
563
|
+
* to targets and upstream proxies will be forcibly aborted.
|
|
564
|
+
* @param callback
|
|
565
|
+
*/
|
|
566
|
+
|
|
567
|
+
}, {
|
|
568
|
+
key: 'close',
|
|
569
|
+
value: function close(closeConnections, callback) {
|
|
570
|
+
if (typeof closeConnections === 'function') {
|
|
571
|
+
callback = closeConnections;
|
|
572
|
+
closeConnections = false;
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
if (closeConnections) {
|
|
576
|
+
this.log(null, 'Closing pending handlers');
|
|
577
|
+
var count = 0;
|
|
578
|
+
_underscore2.default.each(this.handlers, function (handler) {
|
|
579
|
+
count++;
|
|
580
|
+
handler.close();
|
|
581
|
+
});
|
|
582
|
+
this.log(null, 'Destroyed ' + count + ' pending handlers');
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
// TODO: keep track of all handlers and close them if closeConnections=true
|
|
586
|
+
if (this.server) {
|
|
587
|
+
var server = this.server;
|
|
588
|
+
this.server = null;
|
|
589
|
+
return _bluebird2.default.promisify(server.close).bind(server)().nodeify(callback);
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
}]);
|
|
593
|
+
|
|
594
|
+
return Server;
|
|
595
|
+
}(_events2.default);
|