diff --git a/README.md b/README.md index 5d7d334..fc694ad 100644 --- a/README.md +++ b/README.md @@ -216,6 +216,10 @@ Others * to save request data to local file, use ``` anyproxy --file /path/to/file ``` * anyproxy uses [nedb](https://github.com/louischatriot/nedb) to save request data. Since NeDB's persistence uses an append-only format, you may get some redundant record in local file. For those dupplicated ones with the same id, just use the lastest line of record. +#### throttling +* e.g. throttle to 10kb , use ``` anyproxy --throttle 10 ``` +* this is just a rough throttling for downstream, not for network simulation + #### work as a module for nodejs ``` npm install anyproxy --save @@ -233,10 +237,11 @@ var options = { port : 8001, hostname : "localhost", rule : require("path/to/my/ruleModule.js"), - dbFile : null, //save request data to a specified file, will use in-memory db if not specified - webPort : 8002, // port for web interface - socketPort : 8003, // internal port for web socket, replace this when it is conflict with your own service - webConfigPort : 8088 // internal port for web config(beta), replace this when it is conflict with your own service + dbFile : null, // optional, save request data to a specified file, will use in-memory db if not specified + webPort : 8002, // optional, port for web interface + socketPort : 8003, // optional, internal port for web socket, replace this when it is conflict with your own service + webConfigPort : 8088, // optional, internal port for web config(beta), replace this when it is conflict with your own service + throttle : 10, // optional, speed limit in kb/s }; new proxy.proxyServer(options); diff --git a/bin.js b/bin.js index 948bdad..4061c64 100644 --- a/bin.js +++ b/bin.js @@ -12,6 +12,7 @@ program .option('-f, --file [value]', 'save request data to a specified file, will use in-memory db if not specified') .option('-r, --rule [value]', 'path for rule file,') .option('-g, --root [value]', 'generate root CA') + .option('-l, --throttle [value]', 'throttle speed in kb/s') .option('-c, --clear', 'clear all the tmp certificates') .parse(process.argv); @@ -46,6 +47,7 @@ if(program.clear){ port : program.port, hostname : program.hostname, dbFile : program.file, + throttle : program.throttle, rule : ruleModule }); } diff --git a/lib/requestHandler.js b/lib/requestHandler.js index 9fd5e61..f4acd28 100644 --- a/lib/requestHandler.js +++ b/lib/requestHandler.js @@ -9,6 +9,7 @@ var http = require("http"), color = require("colorful"), Buffer = require('buffer').Buffer, util = require("./util"), + Stream = require("stream"), httpsServerMgr = require("./httpsServerMgr"); var httpsServerMgrInstance = new httpsServerMgr(), @@ -109,6 +110,7 @@ function userRequestHandler(req,userRes){ }; options = userRule.replaceRequestOption(req,options) || options; + //update quest data reqData = userRule.replaceRequestData(req,reqData) || reqData; options.headers = util.lower_keys(options.headers); @@ -182,13 +184,19 @@ function userRequestHandler(req,userRes){ //send response },function(callback){ - // if(404 == statusCode){ - // var html404path = pathUtil.join(__dirname, '..', 'web', '404.html'); - // userRes.end(fs.readFileSync(html404path)); - // }else{ + if(GLOBAL._throttle){ + var thrStream = new Stream(); + + var readable = thrStream.pipe(GLOBAL._throttle.throttle()); + readable.pipe(userRes); + + thrStream.emit("data",serverResData); + thrStream.emit("end"); + callback(); + }else{ userRes.end(serverResData); - // } - callback(); + callback(); + } //udpate record info },function(callback){ diff --git a/package.json b/package.json index 2eb9975..e59b741 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "anyproxy", - "version": "2.6.0", + "version": "2.7.0", "description": "A fully configurable proxy in NodeJS, which can handle HTTPS requests perfectly.", "main": "proxy.js", "bin": { @@ -15,14 +15,15 @@ "express": "^4.8.5", "iconv-lite": "^0.4.4", "ip": "^0.3.2", + "jquery": "^2.1.1", + "jsdom": "^1.0.3", "juicer": "^0.6.6-stable", "nedb": "^0.11.0", "qrcode-npm": "0.0.3", "socks5-http-client": "^0.1.6", "socks5-https-client": "^0.2.2", - "ws": "^0.4.32", - "jsdom":"^1.0.3", - "jquery":"^2.1.1" + "stream-throttle": "^0.1.3", + "ws": "^0.4.32" }, "devDependencies": {}, "scripts": { diff --git a/proxy.js b/proxy.js index a7d2756..83c8846 100644 --- a/proxy.js +++ b/proxy.js @@ -1,13 +1,13 @@ //mix some modules to global.util try{ - GLOBAL.util = require('./lib/util'); - GLOBAL.util['iconv-lite'] = require("iconv-lite"); - GLOBAL.util['colorful'] = require("colorful"); - GLOBAL.util['path'] = require("path"); - GLOBAL.util['jsdom'] = require('jsdom'); - GLOBAL.util['jquery'] = require('jquery'); - GLOBAL.util['Socks5ClientHttpAgent'] = require('socks5-http-client/lib/Agent'); - GLOBAL.util['Socks5ClientHttpsAgent'] = require('socks5-https-client/lib/Agent'); + GLOBAL.util = require('./lib/util'); + GLOBAL.util['iconv-lite'] = require("iconv-lite"); + GLOBAL.util['colorful'] = require("colorful"); + GLOBAL.util['path'] = require("path"); + GLOBAL.util['jsdom'] = require('jsdom'); + GLOBAL.util['jquery'] = require('jquery'); + GLOBAL.util['Socks5ClientHttpAgent'] = require('socks5-http-client/lib/Agent'); + GLOBAL.util['Socks5ClientHttpsAgent'] = require('socks5-https-client/lib/Agent'); }catch(e){} var http = require('http'), @@ -28,7 +28,9 @@ var http = require('http'), events = require("events"), express = require("express"), ip = require("ip"), - fork = require("child_process").fork; + fork = require("child_process").fork, + ThrottleGroup = require("stream-throttle").ThrottleGroup; + var T_TYPE_HTTP = 0, T_TYPE_HTTPS = 1, @@ -60,6 +62,7 @@ if(fs.existsSync(process.cwd() + '/rule.js')){ //option.socketPort : 8003(default) //option.webConfigPort : 8088(default) //option.dbFile : null(default) +//option.throttle : null(default) function proxyServer(option){ option = option || {}; @@ -78,6 +81,11 @@ function proxyServer(option){ GLOBAL.recorder = new Recorder(); } + if(option.throttle){ + console.log("throttle :" + option.throttle + "kb/s"); + GLOBAL._throttle = new ThrottleGroup({rate: 1024 * parseInt(option.throttle) }); // rate - byte/sec + } + requestHandler.setRules(proxyRules); //TODO : optimize calling for set rule self.httpProxyServer = null;