From c6c2355d17ee69e2ae3ef9a5a2c682f6854f8648 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8A=A0=E9=87=8C?= Date: Tue, 21 Oct 2014 11:18:55 +0800 Subject: [PATCH] add replaceServerResDataAsync --- README.md | 5 +- lib/old.js | 122 ------------------ lib/requestHandler.js | 14 +- lib/rule_default.js | 9 +- package.json | 3 +- proxy.js | 8 +- rule_sample/rule__blank.js | 9 +- .../rule_intercept_some_https_requests.js | 4 +- rule_sample/rule_replace_response_data.js | 6 +- web/detail.js | 3 - web/list.js | 34 ++--- webServer.js | 20 ++- 12 files changed, 78 insertions(+), 159 deletions(-) delete mode 100644 lib/old.js diff --git a/README.md b/README.md index 0550d3a..2c9e749 100644 --- a/README.md +++ b/README.md @@ -157,9 +157,10 @@ module.exports = { //replace the response from the server before it's sent to the user //you may return either a Buffer or a string //serverResData is a Buffer, you may get its content by calling serverResData.toString() - replaceServerResData: function(req,res,serverResData){ - return serverResData; + replaceServerResDataAsync: function(req,res,serverResData,callback){ + callback(serverResData); }, + //replaceServerResData is deprecated //在请求返回给用户前的延迟时间 //add a pause before sending response to user diff --git a/lib/old.js b/lib/old.js deleted file mode 100644 index 8e048b9..0000000 --- a/lib/old.js +++ /dev/null @@ -1,122 +0,0 @@ -var exec = require('child_process').exec, - spawn = require('child_process').spawn, - path = require("path"), - fs = require("fs"), - os = require("os"), - color = require('colorful'), - readline = require('readline'), - util = require('./util'), - asyncTask = require("async-task-mgr"); - -var certDir = path.join(util.getUserHome(),"/.anyproxy_certs/"), - cmdDir = path.join(__dirname,"..","./cert/"), - asyncTaskMgr = new asyncTask(); - -if(!fs.existsSync(certDir)){ - fs.mkdirSync(certDir); -} - -function getCertificate(hostname,cb){ - var keyFile = path.join(certDir , "__hostname.key".replace(/__hostname/,hostname) ), - crtFile = path.join(certDir , "__hostname.crt".replace(/__hostname/,hostname) ); - - if(!fs.existsSync(keyFile) || !fs.existsSync(crtFile)){ - asyncTaskMgr.addTask(hostname,function(cb){ - createCert(hostname,function(err){ - cb(err ? err : null); - }); - },function(err){ - if(!err){ - cb(null , fs.readFileSync(keyFile) , fs.readFileSync(crtFile) ); - }else{ - cb(err); - } - }); - - }else{ - cb(null , fs.readFileSync(keyFile) , fs.readFileSync(crtFile) ); - } -} - -function createCert(hostname,callback){ - console.log(hostname); - checkRootCA(); - - var cmd = "./gen-cer __host __path".replace(/__host/,hostname).replace(/__path/,certDir); - exec(cmd,{ cwd : cmdDir },function(err,stdout,stderr){ - if(err){ - callback && callback(new Error("error when generating certificate"),null); - }else{ - var tipText = "certificate created for __HOST".replace(/__HOST/,hostname); - console.log(color.yellow(color.bold("[internal https]")) + color.yellow(tipText)); - callback(null); - } - }); -} - -function clearCerts(cb){ - exec("rm *.key *.csr *.crt",{cwd : certDir},cb); -} - -function isRootCAFileExists(){ - var crtFile = path.join(cmdDir,"rootCA.crt"), - keyFile = path.join(cmdDir,"rootCA.key"); - - return (fs.existsSync(crtFile) && fs.existsSync(keyFile)); -} - -function checkRootCA(){ - if(!isRootCAFileExists()){ - console.log(color.red("can not find rootCA.crt or rootCA.key")); - console.log(color.red("you may generate one by the following methods")); - console.log(color.red("\twhen using globally : anyproxy --root")); - console.log(color.red("\twhen using as a module : require(\"anyproxy\").generateRootCA();")); - process.exit(0); - } -} - -function generateRootCA(){ - if(isRootCAFileExists()){ - console.log(color.yellow("rootCA exists at " + certDir)); - var rl = readline.createInterface({ - input: process.stdin, - output: process.stdout - }); - - rl.question("do you really want to generate a new one ?)(yes/NO)", function(answer) { - if(/yes/i.test(answer)){ - startGenerating(); - }else{ - console.log("will not generate a new one"); - process.exit(0); - } - - rl.close(); - }); - }else{ - startGenerating(); - } - - function startGenerating(){ - var spawnSteam = spawn("./gen-rootCA",['.'],{cwd:cmdDir,stdio: 'inherit'}); - - spawnSteam.on('close', function (code) { - if(code == 0){ - console.log(color.green("rootCA generated")); - console.log(color.green(color.bold("please trust the rootCA.crt in " + cmdDir))); - clearCerts(function(){ - console.log(color.green("temp certs cleared")); - process.exit(0); - }); - }else{ - console.log(color.red("fail to generate root CA")); - } - }); - } -} - -module.exports.generateRootCA = generateRootCA; -module.exports.getCertificate = getCertificate; -module.exports.createCert = createCert; -module.exports.clearCerts = clearCerts; -module.exports.isRootCAFileExists = isRootCAFileExists; \ No newline at end of file diff --git a/lib/requestHandler.js b/lib/requestHandler.js index 8371867..9fd5e61 100644 --- a/lib/requestHandler.js +++ b/lib/requestHandler.js @@ -158,8 +158,18 @@ function userRequestHandler(req,userRes){ //get custom response },function(callback){ - serverResData = userRule.replaceServerResData(req,res,serverResData) || serverResData; - callback(); + if(userRule.replaceServerResData){ + console.log(color.red("replaceServerResData is deprecated, and will be unavilable soon. Use replaceServerResDataAsync instead.")); + serverResData = userRule.replaceServerResData(req,res,serverResData) || serverResData; + callback(); + }else if(userRule.replaceServerResDataAsync){ + userRule.replaceServerResDataAsync(req,res,serverResData,function(newRes){ + serverResData = newRes; + callback(); + }); + }else{ + callback(); + } //delay },function(callback){ diff --git a/lib/rule_default.js b/lib/rule_default.js index ac459cf..608dac6 100644 --- a/lib/rule_default.js +++ b/lib/rule_default.js @@ -40,8 +40,13 @@ module.exports = { return mergeCORSHeader(req.headers, header); }, - replaceServerResData: function(req,res,serverResData){ - return serverResData; + // Deprecated + // replaceServerResData: function(req,res,serverResData){ + // return serverResData; + // }, + + replaceServerResDataAsync: function(req,res,serverResData,callback){ + callback(serverResData); }, pauseBeforeSendingResponse : function(req,res){ diff --git a/package.json b/package.json index f6b450d..7db71d5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "anyproxy", - "version": "2.4.7", + "version": "2.5.0", "description": "A fully configurable proxy in NodeJS, which can handle HTTPS requests perfectly.", "main": "proxy.js", "bin": { @@ -17,6 +17,7 @@ "ip": "^0.3.2", "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" diff --git a/proxy.js b/proxy.js index 2808dfc..2954d5c 100644 --- a/proxy.js +++ b/proxy.js @@ -135,12 +135,16 @@ function proxyServer(option){ var configServer = new UIConfigServer(proxyConfigPort); configServer.on("rule_changed",function() { - console.log(arguments); + // console.log(arguments); }) - var tipText = "web interface started at port " + proxyWebPort; + var tipText,webUrl; + webUrl = "http://" + ip.address() + ":" + proxyWebPort +"/"; + tipText = "web interface started at : " + webUrl; console.log(color.green(tipText)); + tipText = "[alpha]qr code to for iOS client: " + webUrl + "qr"; + console.log(color.green(tipText)); callback(null); } ], diff --git a/rule_sample/rule__blank.js b/rule_sample/rule__blank.js index 900107d..3e87c76 100644 --- a/rule_sample/rule__blank.js +++ b/rule_sample/rule__blank.js @@ -96,10 +96,15 @@ module.exports = { //replace the response from the server before it's sent to the user //you may return either a Buffer or a string //serverResData is a Buffer, you may get its content by calling serverResData.toString() - replaceServerResData: function(req,res,serverResData){ - return serverResData; + replaceServerResDataAsync: function(req,res,serverResData,callback){ + callback(serverResData); }, + //Deprecated + // replaceServerResData: function(req,res,serverResData){ + // return serverResData; + // }, + //在请求返回给用户前的延迟时间 //add a pause before sending response to user pauseBeforeSendingResponse : function(req,res){ diff --git a/rule_sample/rule_intercept_some_https_requests.js b/rule_sample/rule_intercept_some_https_requests.js index 10468b4..825e57c 100644 --- a/rule_sample/rule_intercept_some_https_requests.js +++ b/rule_sample/rule_intercept_some_https_requests.js @@ -3,12 +3,12 @@ module.exports = { - replaceServerResData: function(req,res,serverResData){ + replaceServerResDataAsync: function(req,res,serverResData,callback){ //add "hello github" to all github pages if(req.headers.host == "github.com"){ serverResData += "hello github"; } - return serverResData; + callback(serverResData); }, shouldInterceptHttpsReq :function(req){ diff --git a/rule_sample/rule_replace_response_data.js b/rule_sample/rule_replace_response_data.js index 872f5f4..0976ea2 100644 --- a/rule_sample/rule_replace_response_data.js +++ b/rule_sample/rule_replace_response_data.js @@ -2,15 +2,15 @@ module.exports = { - replaceServerResData: function(req,res,serverResData){ + replaceServerResDataAsync: function(req,res,serverResData,callback){ //append "hello world" to all web pages if(/html/i.test(res.headers['content-type'])){ var newDataStr = serverResData.toString(); newDataStr += "hello world!"; - return newDataStr; + callback(newDataStr); }else{ - return serverResData; + callback(serverResData); } } diff --git a/web/detail.js b/web/detail.js index 0dc5c7a..cfab5e8 100644 --- a/web/detail.js +++ b/web/detail.js @@ -36,9 +36,6 @@ define("./detail",['$', 'gallery/underscore/1.6.0/underscore.js'],function(requi '

response body

'+ '
'+ '
'+ - // '
'+ - // ' '+ - // '
'+ '
'+ ' '+ ' <% } %>'; diff --git a/web/list.js b/web/list.js index 77be929..c384222 100644 --- a/web/list.js +++ b/web/list.js @@ -93,7 +93,7 @@ seajs.use(['$', 'Underscore', 'Backbone',"./detail"], function($, _, Backbone,De if(!isInApp){ self.detailPanel.showDetail(detailData); }else{ - window.webkit.messageHandlers.list.postMessage(JSON.stringify(detailData)) + window.webkit.messageHandlers.list.postMessage(JSON.stringify(detailData)); } } }, @@ -174,7 +174,7 @@ seajs.use(['$', 'Underscore', 'Backbone',"./detail"], function($, _, Backbone,De var data = JSON.parse(event.data); var reqDate = new Date(data.startTime); - data.startTimeStr = reqDate.toLocaleTimeString() + ""; + data.startTimeStr = reqDate.format("hh:mm:ss") + ""; var previous; if(previous = recList.get(data.id)){ @@ -238,19 +238,19 @@ seajs.use(['$', 'Underscore', 'Backbone',"./detail"], function($, _, Backbone,De })(); - // Date.prototype.Format = function (fmt) { - // var o = { - // "M+": this.getMonth() + 1, //月份 - // "d+": this.getDate(), //日 - // "h+": this.getHours(), //小时 - // "m+": this.getMinutes(), //分 - // "s+": this.getSeconds(), //秒 - // "q+": Math.floor((this.getMonth() + 3) / 3), //季度 - // "S": this.getMilliseconds() //毫秒 - // }; - // if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length)); - // for (var k in o) if (new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length))); - // return fmt; - // } +}); -}); \ No newline at end of file +Date.prototype.format = function (fmt) { + var o = { + "M+": this.getMonth() + 1, //月份 + "d+": this.getDate(), //日 + "h+": this.getHours(), //小时 + "m+": this.getMinutes(), //分 + "s+": this.getSeconds(), //秒 + "q+": Math.floor((this.getMonth() + 3) / 3), //季度 + "S": this.getMilliseconds() //毫秒 + }; + if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length)); + for (var k in o) if (new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length))); + return fmt; +} \ No newline at end of file diff --git a/webServer.js b/webServer.js index 4eba983..4fd2209 100644 --- a/webServer.js +++ b/webServer.js @@ -6,10 +6,12 @@ var express = require("express"), events = require("events"), inherits = require("util").inherits, entities = require("entities"), + qrCode = require('qrcode-npm'), WebSocketServer = require('ws').Server; function proxyWebServer(port,webSocketPort,proxyConfigPort,ruleSummary,ipAddress){ - var self = this; + var self = this, + myAbsAddress = "http://" + ipAddress + ":" + port +"/"; if(arguments.length < 3){ throw new Error("please assign ports"); @@ -44,6 +46,22 @@ function proxyWebServer(port,webSocketPort,proxyConfigPort,ruleSummary,ipAddress }); }); + //make qr code + app.get("/qr",function(req,res){ + var qr = qrCode.qrcode(4, 'M'), + targetUrl = myAbsAddress, + qrImageTag, + resDom; + + qr.addData(targetUrl); + qr.make(); + qrImageTag = qr.createImgTag(4); + + resDom = ' __img
click or scan qr code to start client
'.replace(/__url/,targetUrl).replace(/__img/,qrImageTag); + res.setHeader("Content-Type", "text/html"); + res.end(resDom); + }); + app.use(function(req,res,next){ var indexHTML = fs.readFileSync(__dirname + "/web/index.html",{encoding:"utf8"});