update post body recorder

This commit is contained in:
加里
2014-09-02 14:54:45 +08:00
parent e92bfe2ae8
commit 8ad15162fa
17 changed files with 163 additions and 266 deletions

View File

@@ -82,6 +82,7 @@ function normalizeInfo(id,info){
//req
singleRecord.reqHeader = info.req.headers;
singleRecord.startTime = info.startTime;
singleRecord.reqBody = info.reqBody || "";
//res
if(info.endTime){
@@ -105,7 +106,6 @@ function normalizeInfo(id,info){
singleRecord.duration = "";
}
return singleRecord;
}

View File

@@ -8,10 +8,12 @@ var http = require("http"),
async = require('async'),
color = require("colorful"),
Buffer = require('buffer').Buffer,
util = require("./util"),
httpsServerMgr = require("./httpsServerMgr");
var httpsServerMgrInstance = new httpsServerMgr(),
userRule = require("./rule_default.js"); //default rule file
defaultRule = require("./rule_default.js"),
userRule = defaultRule; //init
function userRequestHandler(req,userRes){
var host = req.headers.host,
@@ -19,7 +21,8 @@ function userRequestHandler(req,userRes){
path = urlPattern.path,
protocol = (!!req.connection.encrypted && !/http:/.test(req.url)) ? "https" : "http",
resourceInfo,
resourceInfoId = -1;
resourceInfoId = -1,
reqData;
//record
resourceInfo = {
@@ -30,84 +33,113 @@ function userRequestHandler(req,userRes){
req : req,
startTime : new Date().getTime()
};
try{
if(GLOBAL.recorder){
resourceInfoId = GLOBAL.recorder.appendRecord(resourceInfo);
}catch(e){}
}
console.log(color.green("\nreceived request to : " + host + path));
/*
req.url is wired
in http server : http://www.example.com/a/b/c
in https server : /work/alibaba
*/
if(userRule.shouldUseLocalResponse(req)){
console.log("==>use local rules");
userRule.dealLocalResponse(req,function(statusCode,resHeader,resBody){
//get request body and route to local or remote
async.series([fetchReqData,routeReq],function(){});
//get request body
function fetchReqData(callback){
var postData = [];
req.on("data",function(chunk){
postData.push(chunk);
});
req.on("end",function(){
reqData = Buffer.concat(postData);
resourceInfo.reqBody = reqData.toString();
GLOBAL.recorder && GLOBAL.recorder.updateRecord(resourceInfoId,resourceInfo);
callback();
});
}
//route to dealing function
function routeReq(callback){
if(userRule.shouldUseLocalResponse(req,reqData)){
console.log("==>use local rules");
dealWithLocalResponse(callback);
}else{
console.log("==>will forward to real server by proxy");
dealWithRemoteResonse(callback);
}
}
function dealWithLocalResponse(callback){
userRule.dealLocalResponse(req,reqData,function(statusCode,resHeader,resBody){
//update record info
resourceInfo.endTime = new Date().getTime();
resourceInfo.res = { //construct a self-defined res object
statusCode : statusCode || "",
headers : resHeader || {}
headers : resHeader || {}
}
resourceInfo.resBody = resBody;
resourceInfo.length = resBody.length;
try{
GLOBAL.recorder.updateRecord(resourceInfoId,resourceInfo);
}catch(e){}
resourceInfo.resHeader = resHeader || {};
resourceInfo.resBody = resBody;
resourceInfo.length = resBody.length;
resourceInfo.statusCode = statusCode;
GLOBAL.recorder && GLOBAL.recorder.updateRecord(resourceInfoId,resourceInfo);
userRes.writeHead(statusCode,resHeader);
userRes.end(resBody);
callback && callback();
});
return;
}
}else{
console.log("==>will forward to real server by proxy");
function dealWithRemoteResonse(callback){
var options;
//modify protocol if needed
//modify request protocol
protocol = userRule.replaceRequestProtocol(req,protocol) || protocol;
var options = {
//modify request options
options = {
hostname : urlPattern.hostname || req.headers.host,
port : urlPattern.port || req.port || (/https/.test(protocol) ? 443 : 80),
path : path,
method : req.method,
headers : req.headers
};
//modify request options
options = userRule.replaceRequestOption(req,options) || options;
//update quest data
reqData = userRule.replaceRequestData(req,reqData) || reqData;
options.headers = util.lower_keys(options.headers);
options.headers["content-length"] = reqData.length; //rewrite content length info
//send request
var proxyReq = ( /https/.test(protocol) ? https : http).request(options, function(res) {
//deal response header
var statusCode = res.statusCode;
statusCode = userRule.replaceResponseStatusCode(req,res,statusCode) || statusCode;
var resHeader = userRule.replaceResponseHeader(req,res,res.headers) || res.headers;
resHeader = lower_keys(resHeader);
resHeader = util.lower_keys(resHeader);
/* remove gzip related header, and ungzip the content */
// remove gzip related header, and ungzip the content
var ifServerGzipped = /gzip/i.test(resHeader['content-encoding']);
delete resHeader['content-encoding'];
delete resHeader['content-length'];
userRes.writeHead(statusCode, resHeader);
//waiting for data
var resData = [],
length;
//deal response data
var length,
resData = [];
res.on("data",function(chunk){
resData.push(chunk);
});
res.on("end",function(){
var serverResData,
userCustomResData;
var serverResData;
async.series([
@@ -125,9 +157,7 @@ function userRequestHandler(req,userRes){
//get custom response
},function(callback){
userCustomResData = userRule.replaceServerResData(req,res,serverResData);
serverResData = userCustomResData || serverResData;
serverResData = userRule.replaceServerResData(req,res,serverResData) || serverResData;
callback();
//delay
@@ -152,15 +182,13 @@ function userRequestHandler(req,userRes){
resourceInfo.resBody = serverResData;
resourceInfo.length = serverResData.length;
try{
GLOBAL.recorder.updateRecord(resourceInfoId,resourceInfo);
}catch(e){}
GLOBAL.recorder && GLOBAL.recorder.updateRecord(resourceInfoId,resourceInfo);
callback();
}
],function(err,result){
callback && callback();
});
});
@@ -175,7 +203,7 @@ function userRequestHandler(req,userRes){
userRes.end();
});
req.pipe(proxyReq);
proxyReq.end(reqData);
}
}
@@ -255,9 +283,7 @@ function connectReqHandler(req, socket, head){
resourceInfo.resBody = "";
resourceInfo.length = 0;
try{
GLOBAL.recorder.updateRecord(resourceInfoId,resourceInfo);
}catch(e){}
GLOBAL.recorder && GLOBAL.recorder.updateRecord(resourceInfoId,resourceInfo);
callback();
}
@@ -269,26 +295,21 @@ function connectReqHandler(req, socket, head){
});
}
// {"Content-Encoding":"gzip"} --> {"content-encoding":"gzip"}
function lower_keys(obj){
for(var key in obj){
var val = obj[key];
delete obj[key];
obj[key.toLowerCase()] = val;
}
return obj;
}
function setRules(newRule){
if(!newRule){
return;
}else{
userRule = newRule;
userRule = util.merge(defaultRule,newRule);
}
}
module.exports.userRequestHandler = userRequestHandler;
module.exports.connectReqHandler = connectReqHandler;
module.exports.setRules = setRules;
/*
note
req.url is wired
in http server : http://www.example.com/a/b/c
in https server : /work/alibaba
*/

View File

@@ -1,14 +1,17 @@
module.exports = {
shouldUseLocalResponse : function(req){
shouldUseLocalResponse : function(req,reqBody){
},
dealLocalResponse : function(req,callback){
dealLocalResponse : function(req,reqBody,callback){
},
replaceRequestProtocol:function(req,protocol){
},
replaceRequestOption : function(req,option){
},
replaceRequestProtocol:function(req,protocol){
replaceRequestData: function(req,data){
},
replaceResponseStatusCode: function(req,res,statusCode){

20
lib/util.js Normal file
View File

@@ -0,0 +1,20 @@
// {"Content-Encoding":"gzip"} --> {"content-encoding":"gzip"}
module.exports.lower_keys = function(obj){
for(var key in obj){
var val = obj[key];
delete obj[key];
obj[key.toLowerCase()] = val;
}
return obj;
}
module.exports.merge = function(baseObj, extendObj){
for(var key in extendObj){
baseObj[key] = extendObj[key];
}
return baseObj;
}