diff --git a/lib/recorder.js b/lib/recorder.js index 5c5f444..adbb58b 100644 --- a/lib/recorder.js +++ b/lib/recorder.js @@ -4,6 +4,7 @@ var zlib = require('zlib'), util = require("util"), fs = require("fs"), events = require('events'), + iconv = require('iconv-lite'), logUtil = require("./log"); //option.filename @@ -82,8 +83,6 @@ function Recorder(option){ } }; - - self.getBody = function(id){ if(id < 0){ return ""; @@ -92,6 +91,39 @@ function Recorder(option){ return self.recordBodyMap[id] || ""; }; + + self.getBodyUTF8 = function(id,cb){ + + var bodyContent = self.getBody(id), + result = ""; + + GLOBAL.recorder.getSingleRecord(id,function(err,doc){ + //check whether this record exists + if(!doc || !doc[0]){ + cb(new Error("failed to find record for this id")); + return; + } + + if(!bodyContent){ + cb(null,result); + } + + var record = doc[0], + resHeader = record['resHeader'] || {}; + try{ + var charsetMatch = JSON.stringify(resHeader).match(/charset="?([a-zA-Z0-9\-]+)"?/); + if(charsetMatch && charsetMatch.length > 1){ + var currentCharset = charsetMatch[1].toLowerCase(); + if(currentCharset != "utf-8" && iconv.encodingExists(currentCharset)){ + bodyContent = iconv.decode(bodyContent, currentCharset); + } + } + }catch(e){} + + cb(null,bodyContent.toString()); + }); + } + self.getSingleRecord = function(id,cb){ db.find({_id:parseInt(id)},cb); } diff --git a/proxy.js b/proxy.js index 3473e0e..bcb7efd 100644 --- a/proxy.js +++ b/proxy.js @@ -3,28 +3,30 @@ try{ }catch(e){} var http = require('http'), - https = require('https'), - fs = require('fs'), - async = require("async"), - url = require('url'), - program = require('commander'), - color = require('colorful'), - certMgr = require("./lib/certMgr"), - getPort = require("./lib/getPort"), - requestHandler = require("./lib/requestHandler"), - Recorder = require("./lib/recorder"), - logUtil = require("./lib/log"), - inherits = require("util").inherits, - util = require("./lib/util"), - path = require("path"), - juicer = require('juicer'), - events = require("events"), - express = require("express"), - ip = require("ip"), - fork = require("child_process").fork, - ThrottleGroup = require("stream-throttle").ThrottleGroup, - iconv = require('iconv-lite'), - Buffer = require('buffer').Buffer; + https = require('https'), + fs = require('fs'), + async = require("async"), + url = require('url'), + program = require('commander'), + color = require('colorful'), + certMgr = require("./lib/certMgr"), + getPort = require("./lib/getPort"), + requestHandler = require("./lib/requestHandler"), + Recorder = require("./lib/recorder"), + logUtil = require("./lib/log"), + inherits = require("util").inherits, + util = require("./lib/util"), + path = require("path"), + juicer = require('juicer'), + events = require("events"), + express = require("express"), + ip = require("ip"), + fork = require("child_process").fork, + ThrottleGroup = require("stream-throttle").ThrottleGroup, + iconv = require('iconv-lite'), + Buffer = require('buffer').Buffer, + WebSocketServer = require('ws').Server; + var T_TYPE_HTTP = 0, T_TYPE_HTTPS = 1, @@ -81,7 +83,9 @@ function proxyServer(option){ socketPort = option.socketPort || DEFAULT_WEBSOCKET_PORT, //port for websocket proxyConfigPort = option.webConfigPort || DEFAULT_CONFIG_PORT, //port to ui config server disableWebInterface = !!option.disableWebInterface, - ifSilent = !!option.silent; + ifSilent = !!option.silent, + wss, + child_webServer; if(ifSilent){ logUtil.setPrintStatus(false); @@ -128,10 +132,11 @@ function proxyServer(option){ } }, - //listen CONNECT method for https over http function(callback){ + //listen CONNECT request for https over http self.httpProxyServer.on('connect',requestHandler.connectReqHandler); + //start proxy server self.httpProxyServer.listen(proxyPort); callback(null); }, @@ -140,9 +145,8 @@ function proxyServer(option){ function(callback){ if(disableWebInterface){ logUtil.printLog('web interface is disabled'); - callback(null); }else{ - + //[beta] customMenu var customMenuConfig = proxyRules.customMenu, menuList = [], menuListStr; @@ -156,85 +160,112 @@ function proxyServer(option){ //web interface var args = [proxyWebPort, socketPort, proxyConfigPort, requestHandler.getRuleSummary(), ip.address(),menuListStr]; - var child_webServer = fork(path.join(__dirname,"./webServer.js"),args); - child_webServer.on("message",function(data){ - if(data.type == "reqBody" && data.id){ + child_webServer = fork(path.join(__dirname,"./webServer.js"),args); - GLOBAL.recorder.getSingleRecord(data.id,function(err,doc){ - var result; - try{ - var record = doc[0], - resHeader = record['resHeader'] || {}, - bodyContent = GLOBAL.recorder.getBody(data.id); + //deal websocket data + var wsDataDealer = function(){}; + inherits(wsDataDealer,events.EventEmitter); + var dealer = new wsDataDealer(); - result = bodyContent; - //detect charset and convert to utf8 for web interface - try{ - var charsetMatch = JSON.stringify(resHeader).match(/charset="?([a-zA-Z0-9\-]+)"?/); - if(charsetMatch && charsetMatch.length > 1){ - var currentCharset = charsetMatch[1].toLowerCase(); - if(currentCharset != "utf-8" && iconv.encodingExists(currentCharset)){ - result = iconv.decode(bodyContent, currentCharset); - } - } - }catch(e){} + GLOBAL.recorder.on("update",function(data){ + wss && wss.broadcast({ + type : "update", + content: data + }); + }); - child_webServer.send({ - type : "body", - id : data.id, - body : result.toString() - }); - }catch(e){ - child_webServer.send({ + dealer.on("message",function(ws,jsonData){ + if(jsonData.type == "reqBody" && jsonData.id){ + GLOBAL.recorder.getBodyUTF8(jsonData.id, function(err, data){ + var result = {}; + + if(err){ + result = { type : "body", id : null, body : null, - error:e.toString() - }); + error: err.toString() + }; + }else{ + result = { + type : "body", + id : data.id, + body : data + }; } + ws.send(JSON.stringify(result)); }); } }); + dealer.on("message",function(ws,jsonData){ + // another dealer here... + }); + + //web socket interface + wss = new WebSocketServer({port: socketPort}); + wss.on("connection",function(ws){ + ws.on("message",function(msg){ + try{ + var msgObj = JSON.parse(msg); + dealer && dealer.emit("message",ws,msgObj); + }catch(e){ + var result = { + type : "error", + error: "failed to parse your request : " + e.toString() + }; + ws.send(JSON.stringify(result)); + } + }); + }); + wss.broadcast = function(data) { + if(typeof data == "object"){ + data = JSON.stringify(data); + } + + for(var i in this.clients){ + try{ + this.clients[i].send(data); + }catch(e){ + logUtil.printLog("websocket failed to send data, " + e, logUtil.T_ERR); + } + } + }; + //watch dog setInterval(function(argument) { child_webServer.send({ type:"watch" }); },5000); - - //kill web server when father process exits - process.on("exit",function(code){ - child_webServer.kill(); - logUtil.printLog('AnyProxy is about to exit with code: ' + code, logUtil.T_ERR); - process.exit(); - }); - - process.on("uncaughtException",function(err){ - child_webServer.kill(); - logUtil.printLog('Caught exception: ' + err, logUtil.T_ERR); - process.exit(); - }); - - GLOBAL.recorder.on("update",function(data){ - child_webServer.send({ - type: "update", - body: data - }); - }); - - var configServer = new UIConfigServer(proxyConfigPort); - configServer.on("rule_changed",function() {}); - - var tipText,webUrl; - webUrl = "http://" + ip.address() + ":" + proxyWebPort +"/"; - tipText = "GUI interface started at : " + webUrl; - logUtil.printLog(color.green(tipText)); - - // tipText = "[alpha]qr code to for iOS client: " + webUrl + "qr"; - // logUtil.printLog(color.green(tipText)); - callback(null); } + callback(null); + }, + + //server status manager + function(callback){ + + //kill web server when father process exits + process.on("exit",function(code){ + child_webServer.kill(); + logUtil.printLog('AnyProxy is about to exit with code: ' + code, logUtil.T_ERR); + process.exit(); + }); + + process.on("uncaughtException",function(err){ + child_webServer.kill(); + logUtil.printLog('Caught exception: ' + err, logUtil.T_ERR); + process.exit(); + }); + + var tipText,webUrl; + webUrl = "http://" + ip.address() + ":" + proxyWebPort +"/"; + tipText = "GUI interface started at : " + webUrl; + logUtil.printLog(color.green(tipText)); + + // tipText = "[alpha]qr code to for iOS client: " + webUrl + "qr"; + // logUtil.printLog(color.green(tipText)); + callback(null); } ], @@ -334,7 +365,9 @@ function UIConfigServer(port){ self.app = app; } -inherits(UIConfigServer, events.EventEmitter); +// var configServer = new UIConfigServer(proxyConfigPort); +// configServer.on("rule_changed",function() {}); +// inherits(UIConfigServer, events.EventEmitter); module.exports.proxyServer = proxyServer; diff --git a/test_ws.js b/test_ws.js new file mode 100644 index 0000000..a3dcbab --- /dev/null +++ b/test_ws.js @@ -0,0 +1,26 @@ +var WebSocket = require('ws'); +var ws = new WebSocket('ws://127.0.0.1:8003/'); + +ws.on('open', function open() { + console.log("open"); +}); + +ws.on('message', function(data, flags) { + console.log("new msg:"); + + try{ + var dataObj = JSON.parse(data); + console.log(dataObj); + testBody(dataObj.content.id); + }catch(e){} +}); + +function testBody(id){ + var reqData = { + type:"reqBody", + id:id + }; + + ws.send(JSON.stringify(reqData),{binary:false}); +} + diff --git a/web/detail.js b/web/detail.js index d7a550e..bd8774b 100644 --- a/web/detail.js +++ b/web/detail.js @@ -43,21 +43,23 @@ define("./detail",['$', 'gallery/underscore/1.6.0/underscore.js'],function(requi function render(data,cb){ var $baseTpl = $(_.template(tpl, data)); - if(data.statusCode){ //if finished - $.ajax({ - url : "/body?id=" + data._id, - headers : { - anyproxy_web_req : true - }, - type : "GET", - success : function(data){ - $(".J_responseBody", $baseTpl).html(data); - cb($baseTpl); - } - }); - }else{ - cb($baseTpl); - } + cb($baseTpl); + + // if(data.statusCode){ //if finished + // $.ajax({ + // url : "/body?id=" + data._id, + // headers : { + // anyproxy_web_req : true + // }, + // type : "GET", + // success : function(data){ + // $(".J_responseBody", $baseTpl).html(data); + // cb($baseTpl); + // } + // }); + // }else{ + // cb($baseTpl); + // } } exports.render = render; diff --git a/web/list.js b/web/list.js index e1aaaf3..cad3525 100644 --- a/web/list.js +++ b/web/list.js @@ -183,21 +183,28 @@ seajs.use(['$', 'Underscore', 'Backbone',"Handlebars","Popup","./detail"], funct dataSocket.onmessage = function(event){ if(ifPause) return; - var data = JSON.parse(event.data); + try{ + var data = JSON.parse(event.data); - var reqDate = new Date(data.startTime); - data.startTimeStr = reqDate.format("hh:mm:ss") + ""; + if(data.type == 'update'){ + var content = data.content; + var reqDate = new Date(content.startTime); + content.startTimeStr = reqDate.format("hh:mm:ss") + ""; - var previous; - if(previous = recList.get(data.id)){ - previous.set(data); - }else{ - recList.add(new RecordModel(data),{merge: true}); + var previous; + if(previous = recList.get(content.id)){ + previous.set(content); + }else{ + recList.add(new RecordModel(content),{merge: true}); + } + } + + }catch(e){ + console.log(e); } } - dataSocket.onclose = function(e){ - } + dataSocket.onclose = function(e){} dataSocket.onerror = function(e){ console.log(e); diff --git a/webServer.js b/webServer.js index b8f5f2a..c722445 100644 --- a/webServer.js +++ b/webServer.js @@ -8,8 +8,7 @@ var express = require("express"), inherits = require("util").inherits, ent = require("ent"), qrCode = require('qrcode-npm'), - logUtil = require("./lib/log"), - WebSocketServer = require('ws').Server; + logUtil = require("./lib/log"); function proxyWebServer(port,webSocketPort,proxyConfigPort,ruleSummary,ipAddress,menuListStr){ @@ -38,17 +37,6 @@ function proxyWebServer(port,webSocketPort,proxyConfigPort,ruleSummary,ipAddress // }); // }); - app.get("/body",function(req,res){ - var id = req.query.id; - - res.setHeader("Content-Type","text/html"); - res.writeHead(200); - - fetchBody(id,function(body){ - res.end(ent.encode(body)); - }); - }); - app.get("/fetchCrtFile",function(req,res){ if(crtFilePath){ res.setHeader("Content-Type","application/x-x509-ca-cert"); @@ -111,25 +99,7 @@ function proxyWebServer(port,webSocketPort,proxyConfigPort,ruleSummary,ipAddress app.use(express.static(__dirname + '/web')); app.listen(port); - //web socket interface - var wss = new WebSocketServer({port: webSocketPort}); - wss.on("connection",function(ws){}); - wss.broadcast = function(data) { - for(var i in this.clients){ - try{ - this.clients[i].send(data); - }catch(e){ - logUtil.printLog("websocket failed to send data, " + e, logUtil.T_ERR); - } - } - }; - - self.on("update",function(data){ - wss.broadcast( JSON.stringify(data) ); - }) - self.app = app; - self.wss = wss; } inherits(proxyWebServer, events.EventEmitter); @@ -140,37 +110,15 @@ var param = process.argv.slice(2), lastestHeartbeat = new Date().getTime(); +//watch dog process.on("message",function(data){ - - if(data.type == "update"){ - server.emit("update",data.body); - - }else if( data.type == "body"){ - try{ - var key = data.id + ""; - cbMap[key].body = data.body; - cbMap[key].cb.call(null,data.body); - }catch(e){} - }else if(data.type == "watch"){ + if(data.type == "watch"){ lastestHeartbeat = new Date().getTime(); } }); -//watch dog setInterval(function(){ if(new Date().getTime() - lastestHeartbeat > 10 * 1000){ process.exit(); } },7000); - -function fetchBody(id,cb){ - var key = id + ""; - if(cbMap[key]){ - cb(cbMap[key].body); - }else{ - cbMap[key] = { - cb : cb - }; - process.send({type : "reqBody", id: id}); - } -} \ No newline at end of file