mirror of
https://github.com/alibaba/anyproxy.git
synced 2025-04-23 15:51:25 +00:00
fix conflicts
This commit is contained in:
commit
87f4f00ade
39
README.md
39
README.md
@ -29,32 +29,28 @@ How to write your own rule file
|
|||||||
* you may learn how it works by our samples: [https://github.com/alipay-ct-wd/anyproxy/tree/master/rule_sample](https://github.com/alipay-ct-wd/anyproxy/tree/master/rule_sample)
|
* you may learn how it works by our samples: [https://github.com/alipay-ct-wd/anyproxy/tree/master/rule_sample](https://github.com/alipay-ct-wd/anyproxy/tree/master/rule_sample)
|
||||||
* rule file scheme
|
* rule file scheme
|
||||||
```javascript
|
```javascript
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
/*
|
/*
|
||||||
these functions are required
|
these functions will overwrite the default ones, write your own when necessary.
|
||||||
you may leave their bodies blank if necessary
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//whether to intercept this request by local logic
|
//whether to intercept this request by local logic
|
||||||
//if the return value is true, anyproxy will call dealLocalResponse to get response data and will not send request to remote server anymore
|
//if the return value is true, anyproxy will call dealLocalResponse to get response data and will not send request to remote server anymore
|
||||||
shouldUseLocalResponse : function(req){
|
shouldUseLocalResponse : function(req,reqBody){
|
||||||
return false;
|
if(/hello/.test(reqBody.toString())){
|
||||||
|
return true;
|
||||||
|
}else{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
//you may deal the response locally instead of sending it to server
|
//you may deal the response locally instead of sending it to server
|
||||||
//this function be called when shouldUseLocalResponse returns true
|
//this function be called when shouldUseLocalResponse returns true
|
||||||
//callback(statusCode,resHeader,responseData)
|
//callback(statusCode,resHeader,responseData)
|
||||||
//e.g. callback(200,{"content-type":"text/html"},"hello world")
|
//e.g. callback(200,{"content-type":"text/html"},"hello world")
|
||||||
dealLocalResponse : function(req,callback){
|
dealLocalResponse : function(req,reqBody,callback){
|
||||||
//callback(statusCode,resHeader,responseData)
|
callback(statusCode,resHeader,responseData)
|
||||||
},
|
|
||||||
|
|
||||||
//req is user's request sent to the proxy server
|
|
||||||
// option is how the proxy server will send request to the real server. i.e. require("http").request(option,function(){...})
|
|
||||||
//you may return a customized option to replace the original option
|
|
||||||
replaceRequestOption : function(req,option){
|
|
||||||
var newOption = option;
|
|
||||||
return newOption;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
//replace the request protocol when sending to the real server
|
//replace the request protocol when sending to the real server
|
||||||
@ -64,6 +60,20 @@ module.exports = {
|
|||||||
return newProtocol;
|
return newProtocol;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
//req is user's request sent to the proxy server
|
||||||
|
//option is how the proxy server will send request to the real server. i.e. require("http").request(option,function(){...})
|
||||||
|
//you may return a customized option to replace the original option
|
||||||
|
//you should not write content-length header in options, since anyproxy will handle it for you
|
||||||
|
replaceRequestOption : function(req,option){
|
||||||
|
var newOption = option;
|
||||||
|
return newOption;
|
||||||
|
},
|
||||||
|
|
||||||
|
//replace the request body
|
||||||
|
replaceRequestData: function(req,data){
|
||||||
|
return data;
|
||||||
|
},
|
||||||
|
|
||||||
//replace the statusCode before it's sent to the user
|
//replace the statusCode before it's sent to the user
|
||||||
replaceResponseStatusCode: function(req,res,statusCode){
|
replaceResponseStatusCode: function(req,res,statusCode){
|
||||||
var newStatusCode = statusCode;
|
var newStatusCode = statusCode;
|
||||||
@ -96,6 +106,7 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Using https features
|
Using https features
|
||||||
|
@ -82,6 +82,7 @@ function normalizeInfo(id,info){
|
|||||||
//req
|
//req
|
||||||
singleRecord.reqHeader = info.req.headers;
|
singleRecord.reqHeader = info.req.headers;
|
||||||
singleRecord.startTime = info.startTime;
|
singleRecord.startTime = info.startTime;
|
||||||
|
singleRecord.reqBody = info.reqBody || "";
|
||||||
|
|
||||||
//res
|
//res
|
||||||
if(info.endTime){
|
if(info.endTime){
|
||||||
@ -105,7 +106,6 @@ function normalizeInfo(id,info){
|
|||||||
singleRecord.duration = "";
|
singleRecord.duration = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return singleRecord;
|
return singleRecord;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,11 +8,12 @@ var http = require("http"),
|
|||||||
async = require('async'),
|
async = require('async'),
|
||||||
color = require("colorful"),
|
color = require("colorful"),
|
||||||
Buffer = require('buffer').Buffer,
|
Buffer = require('buffer').Buffer,
|
||||||
iconv = require('iconv-lite'),
|
util = require("./util"),
|
||||||
httpsServerMgr = require("./httpsServerMgr");
|
httpsServerMgr = require("./httpsServerMgr");
|
||||||
|
|
||||||
var httpsServerMgrInstance = new 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){
|
function userRequestHandler(req,userRes){
|
||||||
var host = req.headers.host,
|
var host = req.headers.host,
|
||||||
@ -20,7 +21,8 @@ function userRequestHandler(req,userRes){
|
|||||||
path = urlPattern.path,
|
path = urlPattern.path,
|
||||||
protocol = (!!req.connection.encrypted && !/http:/.test(req.url)) ? "https" : "http",
|
protocol = (!!req.connection.encrypted && !/http:/.test(req.url)) ? "https" : "http",
|
||||||
resourceInfo,
|
resourceInfo,
|
||||||
resourceInfoId = -1;
|
resourceInfoId = -1,
|
||||||
|
reqData;
|
||||||
|
|
||||||
//record
|
//record
|
||||||
resourceInfo = {
|
resourceInfo = {
|
||||||
@ -31,84 +33,113 @@ function userRequestHandler(req,userRes){
|
|||||||
req : req,
|
req : req,
|
||||||
startTime : new Date().getTime()
|
startTime : new Date().getTime()
|
||||||
};
|
};
|
||||||
|
if(GLOBAL.recorder){
|
||||||
try{
|
|
||||||
resourceInfoId = GLOBAL.recorder.appendRecord(resourceInfo);
|
resourceInfoId = GLOBAL.recorder.appendRecord(resourceInfo);
|
||||||
}catch(e){}
|
}
|
||||||
|
|
||||||
console.log(color.green("\nreceived request to : " + host + path));
|
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)){
|
//get request body and route to local or remote
|
||||||
console.log("==>use local rules");
|
async.series([fetchReqData,routeReq],function(){});
|
||||||
userRule.dealLocalResponse(req,function(statusCode,resHeader,resBody){
|
|
||||||
|
//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
|
//update record info
|
||||||
resourceInfo.endTime = new Date().getTime();
|
resourceInfo.endTime = new Date().getTime();
|
||||||
resourceInfo.res = { //construct a self-defined res object
|
resourceInfo.res = { //construct a self-defined res object
|
||||||
statusCode : statusCode || "",
|
statusCode : statusCode || "",
|
||||||
headers : resHeader || {}
|
headers : resHeader || {}
|
||||||
}
|
}
|
||||||
resourceInfo.resBody = resBody;
|
resourceInfo.resHeader = resHeader || {};
|
||||||
resourceInfo.length = resBody.length;
|
resourceInfo.resBody = resBody;
|
||||||
|
resourceInfo.length = resBody.length;
|
||||||
try{
|
resourceInfo.statusCode = statusCode;
|
||||||
GLOBAL.recorder.updateRecord(resourceInfoId,resourceInfo);
|
|
||||||
}catch(e){}
|
GLOBAL.recorder && GLOBAL.recorder.updateRecord(resourceInfoId,resourceInfo);
|
||||||
|
|
||||||
userRes.writeHead(statusCode,resHeader);
|
userRes.writeHead(statusCode,resHeader);
|
||||||
userRes.end(resBody);
|
userRes.end(resBody);
|
||||||
|
callback && callback();
|
||||||
});
|
});
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
}else{
|
function dealWithRemoteResonse(callback){
|
||||||
console.log("==>will forward to real server by proxy");
|
var options;
|
||||||
|
|
||||||
//modify protocol if needed
|
//modify request protocol
|
||||||
protocol = userRule.replaceRequestProtocol(req,protocol) || protocol;
|
protocol = userRule.replaceRequestProtocol(req,protocol) || protocol;
|
||||||
|
|
||||||
var options = {
|
//modify request options
|
||||||
|
options = {
|
||||||
hostname : urlPattern.hostname || req.headers.host,
|
hostname : urlPattern.hostname || req.headers.host,
|
||||||
port : urlPattern.port || req.port || (/https/.test(protocol) ? 443 : 80),
|
port : urlPattern.port || req.port || (/https/.test(protocol) ? 443 : 80),
|
||||||
path : path,
|
path : path,
|
||||||
method : req.method,
|
method : req.method,
|
||||||
headers : req.headers
|
headers : req.headers
|
||||||
};
|
};
|
||||||
|
|
||||||
//modify request options
|
|
||||||
options = userRule.replaceRequestOption(req,options) || 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) {
|
var proxyReq = ( /https/.test(protocol) ? https : http).request(options, function(res) {
|
||||||
|
|
||||||
|
//deal response header
|
||||||
var statusCode = res.statusCode;
|
var statusCode = res.statusCode;
|
||||||
statusCode = userRule.replaceResponseStatusCode(req,res,statusCode) || statusCode;
|
statusCode = userRule.replaceResponseStatusCode(req,res,statusCode) || statusCode;
|
||||||
|
|
||||||
var resHeader = userRule.replaceResponseHeader(req,res,res.headers) || res.headers;
|
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']);
|
var ifServerGzipped = /gzip/i.test(resHeader['content-encoding']);
|
||||||
delete resHeader['content-encoding'];
|
delete resHeader['content-encoding'];
|
||||||
delete resHeader['content-length'];
|
delete resHeader['content-length'];
|
||||||
|
|
||||||
userRes.writeHead(statusCode, resHeader);
|
userRes.writeHead(statusCode, resHeader);
|
||||||
|
|
||||||
//waiting for data
|
//deal response data
|
||||||
var resData = [],
|
var length,
|
||||||
length;
|
resData = [];
|
||||||
|
|
||||||
res.on("data",function(chunk){
|
res.on("data",function(chunk){
|
||||||
resData.push(chunk);
|
resData.push(chunk);
|
||||||
});
|
});
|
||||||
|
|
||||||
res.on("end",function(){
|
res.on("end",function(){
|
||||||
|
var serverResData;
|
||||||
var serverResData,
|
|
||||||
userCustomResData;
|
|
||||||
|
|
||||||
async.series([
|
async.series([
|
||||||
|
|
||||||
@ -126,9 +157,7 @@ function userRequestHandler(req,userRes){
|
|||||||
|
|
||||||
//get custom response
|
//get custom response
|
||||||
},function(callback){
|
},function(callback){
|
||||||
|
serverResData = userRule.replaceServerResData(req,res,serverResData) || serverResData;
|
||||||
userCustomResData = userRule.replaceServerResData(req,res,serverResData);
|
|
||||||
serverResData = userCustomResData || serverResData;
|
|
||||||
callback();
|
callback();
|
||||||
|
|
||||||
//delay
|
//delay
|
||||||
@ -153,15 +182,13 @@ function userRequestHandler(req,userRes){
|
|||||||
resourceInfo.resBody = serverResData;
|
resourceInfo.resBody = serverResData;
|
||||||
resourceInfo.length = serverResData.length;
|
resourceInfo.length = serverResData.length;
|
||||||
|
|
||||||
try{
|
GLOBAL.recorder && GLOBAL.recorder.updateRecord(resourceInfoId,resourceInfo);
|
||||||
GLOBAL.recorder.updateRecord(resourceInfoId,resourceInfo);
|
|
||||||
}catch(e){}
|
|
||||||
|
|
||||||
callback();
|
callback();
|
||||||
}
|
}
|
||||||
|
|
||||||
],function(err,result){
|
],function(err,result){
|
||||||
|
callback && callback();
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
@ -176,7 +203,7 @@ function userRequestHandler(req,userRes){
|
|||||||
userRes.end();
|
userRes.end();
|
||||||
});
|
});
|
||||||
|
|
||||||
req.pipe(proxyReq);
|
proxyReq.end(reqData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -256,9 +283,7 @@ function connectReqHandler(req, socket, head){
|
|||||||
resourceInfo.resBody = "";
|
resourceInfo.resBody = "";
|
||||||
resourceInfo.length = 0;
|
resourceInfo.length = 0;
|
||||||
|
|
||||||
try{
|
GLOBAL.recorder && GLOBAL.recorder.updateRecord(resourceInfoId,resourceInfo);
|
||||||
GLOBAL.recorder.updateRecord(resourceInfoId,resourceInfo);
|
|
||||||
}catch(e){}
|
|
||||||
|
|
||||||
callback();
|
callback();
|
||||||
}
|
}
|
||||||
@ -270,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){
|
function setRules(newRule){
|
||||||
if(!newRule){
|
if(!newRule){
|
||||||
return;
|
return;
|
||||||
}else{
|
}else{
|
||||||
userRule = newRule;
|
userRule = util.merge(defaultRule,newRule);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports.userRequestHandler = userRequestHandler;
|
module.exports.userRequestHandler = userRequestHandler;
|
||||||
module.exports.connectReqHandler = connectReqHandler;
|
module.exports.connectReqHandler = connectReqHandler;
|
||||||
module.exports.setRules = setRules;
|
module.exports.setRules = setRules;
|
||||||
|
|
||||||
|
/*
|
||||||
|
note
|
||||||
|
req.url is wired
|
||||||
|
in http server : http://www.example.com/a/b/c
|
||||||
|
in https server : /work/alibaba
|
||||||
|
*/
|
||||||
|
@ -1,20 +1,33 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
shouldUseLocalResponse : function(req){
|
shouldUseLocalResponse : function(req,reqBody){
|
||||||
|
//intercept all options request
|
||||||
|
if(req.method == "OPTIONS"){
|
||||||
|
return true;
|
||||||
|
}else{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
dealLocalResponse : function(req,callback){
|
dealLocalResponse : function(req,reqBody,callback){
|
||||||
|
if(req.method == "OPTIONS"){
|
||||||
|
callback(200,mergeCORSHeader(req.headers),"");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
replaceRequestProtocol:function(req,protocol){
|
||||||
},
|
},
|
||||||
|
|
||||||
replaceRequestOption : function(req,option){
|
replaceRequestOption : function(req,option){
|
||||||
},
|
},
|
||||||
|
|
||||||
replaceRequestProtocol:function(req,protocol){
|
replaceRequestData: function(req,data){
|
||||||
},
|
},
|
||||||
|
|
||||||
replaceResponseStatusCode: function(req,res,statusCode){
|
replaceResponseStatusCode: function(req,res,statusCode){
|
||||||
},
|
},
|
||||||
|
|
||||||
replaceResponseHeader: function(req,res,header){
|
replaceResponseHeader: function(req,res,header){
|
||||||
|
return mergeCORSHeader(req.headers, header);
|
||||||
},
|
},
|
||||||
|
|
||||||
replaceServerResData: function(req,res,serverResData){
|
replaceServerResData: function(req,res,serverResData){
|
||||||
@ -25,4 +38,20 @@ module.exports = {
|
|||||||
|
|
||||||
shouldInterceptHttpsReq :function(req){
|
shouldInterceptHttpsReq :function(req){
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function mergeCORSHeader(reqHeader,originHeader){
|
||||||
|
var targetObj = originHeader || {};
|
||||||
|
|
||||||
|
delete targetObj["Access-Control-Allow-Credentials"];
|
||||||
|
delete targetObj["Access-Control-Allow-Origin"];
|
||||||
|
delete targetObj["Access-Control-Allow-Methods"];
|
||||||
|
delete targetObj["Access-Control-Allow-Headers"];
|
||||||
|
|
||||||
|
targetObj["access-control-allow-credentials"] = "true";
|
||||||
|
targetObj["access-control-allow-origin"] = reqHeader['origin'] || "-___-||";
|
||||||
|
targetObj["access-control-allow-methods"] = "GET, POST, PUT";
|
||||||
|
targetObj["access-control-allow-headers"] = reqHeader['access-control-request-headers'] || "-___-||";
|
||||||
|
|
||||||
|
return targetObj;
|
||||||
|
}
|
20
lib/util.js
Normal file
20
lib/util.js
Normal 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;
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "anyproxy",
|
"name": "anyproxy",
|
||||||
"version": "2.0.0",
|
"version": "2.1.1",
|
||||||
"description": "a charles/fiddler like proxy written in NodeJs, which can handle HTTPS requests and CROS perfectly.",
|
"description": "a charles/fiddler like proxy written in NodeJs, which can handle HTTPS requests and CROS perfectly.",
|
||||||
"main": "proxy.js",
|
"main": "proxy.js",
|
||||||
"bin": {
|
"bin": {
|
||||||
@ -13,6 +13,7 @@
|
|||||||
"commander": "~2.3.0",
|
"commander": "~2.3.0",
|
||||||
"entities": "^1.1.1",
|
"entities": "^1.1.1",
|
||||||
"express": "^4.8.5",
|
"express": "^4.8.5",
|
||||||
|
"iconv-lite": "^0.4.4",
|
||||||
"nedb": "^0.11.0",
|
"nedb": "^0.11.0",
|
||||||
"ws": "^0.4.32",
|
"ws": "^0.4.32",
|
||||||
"iconv-lite": "^0.4.4"
|
"iconv-lite": "^0.4.4"
|
||||||
|
10
proxy.js
10
proxy.js
@ -15,6 +15,12 @@ var http = require('http'),
|
|||||||
|
|
||||||
GLOBAL.recorder = new Recorder();
|
GLOBAL.recorder = new Recorder();
|
||||||
|
|
||||||
|
//mix some modules to global.util
|
||||||
|
try{
|
||||||
|
GLOBAL.util = {};
|
||||||
|
GLOBAL.util['iconv-lite'] = require("iconv-lite");
|
||||||
|
}catch(e){}
|
||||||
|
|
||||||
var T_TYPE_HTTP = 0,
|
var T_TYPE_HTTP = 0,
|
||||||
T_TYPE_HTTPS = 1,
|
T_TYPE_HTTPS = 1,
|
||||||
DEFAULT_PORT = 8001,
|
DEFAULT_PORT = 8001,
|
||||||
@ -138,9 +144,7 @@ function startWebServer(port){
|
|||||||
|
|
||||||
//web socket interface
|
//web socket interface
|
||||||
var wss = new WebSocketServer({port: DEFAULT_WEBSOCKET_PORT});
|
var wss = new WebSocketServer({port: DEFAULT_WEBSOCKET_PORT});
|
||||||
wss.on("connection",function(ws){
|
wss.on("connection",function(ws){});
|
||||||
console.log("wss connection");
|
|
||||||
});
|
|
||||||
wss.broadcast = function(data) {
|
wss.broadcast = function(data) {
|
||||||
for(var i in this.clients){
|
for(var i in this.clients){
|
||||||
this.clients[i].send(data);
|
this.clients[i].send(data);
|
||||||
|
@ -1,31 +1,26 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
/*
|
/*
|
||||||
these functions are required
|
these functions will overwrite the default ones, write your own when necessary.
|
||||||
you may leave their bodies blank if necessary
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//whether to intercept this request by local logic
|
//whether to intercept this request by local logic
|
||||||
//if the return value is true, anyproxy will call dealLocalResponse to get response data and will not send request to remote server anymore
|
//if the return value is true, anyproxy will call dealLocalResponse to get response data and will not send request to remote server anymore
|
||||||
shouldUseLocalResponse : function(req){
|
shouldUseLocalResponse : function(req,reqBody){
|
||||||
return false;
|
if(/hello/.test(reqBody.toString())){
|
||||||
|
return true;
|
||||||
|
}else{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
//you may deal the response locally instead of sending it to server
|
//you may deal the response locally instead of sending it to server
|
||||||
//this function be called when shouldUseLocalResponse returns true
|
//this function be called when shouldUseLocalResponse returns true
|
||||||
//callback(statusCode,resHeader,responseData)
|
//callback(statusCode,resHeader,responseData)
|
||||||
//e.g. callback(200,{"content-type":"text/html"},"hello world")
|
//e.g. callback(200,{"content-type":"text/html"},"hello world")
|
||||||
dealLocalResponse : function(req,callback){
|
dealLocalResponse : function(req,reqBody,callback){
|
||||||
//callback(statusCode,resHeader,responseData)
|
callback(statusCode,resHeader,responseData)
|
||||||
},
|
},
|
||||||
|
|
||||||
//req is user's request sent to the proxy server
|
|
||||||
// option is how the proxy server will send request to the real server. i.e. require("http").request(option,function(){...})
|
|
||||||
//you may return a customized option to replace the original option
|
|
||||||
replaceRequestOption : function(req,option){
|
|
||||||
var newOption = option;
|
|
||||||
return newOption;
|
|
||||||
},
|
|
||||||
|
|
||||||
//replace the request protocol when sending to the real server
|
//replace the request protocol when sending to the real server
|
||||||
//protocol : "http" or "https"
|
//protocol : "http" or "https"
|
||||||
replaceRequestProtocol:function(req,protocol){
|
replaceRequestProtocol:function(req,protocol){
|
||||||
@ -33,6 +28,20 @@ module.exports = {
|
|||||||
return newProtocol;
|
return newProtocol;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
//req is user's request sent to the proxy server
|
||||||
|
//option is how the proxy server will send request to the real server. i.e. require("http").request(option,function(){...})
|
||||||
|
//you may return a customized option to replace the original option
|
||||||
|
//you should not write content-length header in options, since anyproxy will handle it for you
|
||||||
|
replaceRequestOption : function(req,option){
|
||||||
|
var newOption = option;
|
||||||
|
return newOption;
|
||||||
|
},
|
||||||
|
|
||||||
|
//replace the request body
|
||||||
|
replaceRequestData: function(req,data){
|
||||||
|
return data;
|
||||||
|
},
|
||||||
|
|
||||||
//replace the statusCode before it's sent to the user
|
//replace the statusCode before it's sent to the user
|
||||||
replaceResponseStatusCode: function(req,res,statusCode){
|
replaceResponseStatusCode: function(req,res,statusCode){
|
||||||
var newStatusCode = statusCode;
|
var newStatusCode = statusCode;
|
||||||
|
@ -1,34 +1,10 @@
|
|||||||
//rule scheme :
|
//rule scheme :
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
shouldUseLocalResponse : function(req){
|
|
||||||
},
|
|
||||||
|
|
||||||
dealLocalResponse : function(req,callback){
|
|
||||||
},
|
|
||||||
|
|
||||||
replaceRequestOption : function(req,option){
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
replaceRequestProtocol:function(req,protocol){
|
|
||||||
},
|
|
||||||
|
|
||||||
replaceResponseStatusCode: function(req,res,statusCode){
|
|
||||||
},
|
|
||||||
|
|
||||||
replaceResponseHeader: function(req,res,header){
|
|
||||||
},
|
|
||||||
|
|
||||||
replaceServerResData: function(req,res,serverResData){
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
pauseBeforeSendingResponse : function(req,res){
|
pauseBeforeSendingResponse : function(req,res){
|
||||||
//delay all the response for 1500ms
|
//delay all the response for 1500ms
|
||||||
return 1500;
|
return 1500;
|
||||||
},
|
|
||||||
|
|
||||||
shouldInterceptHttpsReq :function(req){
|
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
@ -2,7 +2,7 @@
|
|||||||
// Ref: https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
|
// Ref: https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
shouldUseLocalResponse : function(req){
|
shouldUseLocalResponse : function(req,reqBody){
|
||||||
//intercept all options request
|
//intercept all options request
|
||||||
if(req.method == "OPTIONS"){
|
if(req.method == "OPTIONS"){
|
||||||
return true;
|
return true;
|
||||||
@ -11,33 +11,16 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
dealLocalResponse : function(req,callback){
|
dealLocalResponse : function(req,reqBody,callback){
|
||||||
if(req.method == "OPTIONS"){
|
if(req.method == "OPTIONS"){
|
||||||
callback(200,mergeCORSHeader(req.headers),"");
|
callback(200,mergeCORSHeader(req.headers),"");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
replaceRequestOption : function(req,option){
|
|
||||||
},
|
|
||||||
|
|
||||||
replaceRequestProtocol:function(req,protocol){
|
|
||||||
},
|
|
||||||
|
|
||||||
replaceResponseStatusCode: function(req,res,statusCode){
|
|
||||||
},
|
|
||||||
|
|
||||||
replaceResponseHeader: function(req,res,header){
|
replaceResponseHeader: function(req,res,header){
|
||||||
return mergeCORSHeader(req.headers, header);
|
return mergeCORSHeader(req.headers, header);
|
||||||
},
|
|
||||||
|
|
||||||
replaceServerResData: function(req,res,serverResData){
|
|
||||||
},
|
|
||||||
|
|
||||||
pauseBeforeSendingResponse : function(req,res){
|
|
||||||
},
|
|
||||||
|
|
||||||
shouldInterceptHttpsReq :function(req){
|
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function mergeCORSHeader(reqHeader,originHeader){
|
function mergeCORSHeader(reqHeader,originHeader){
|
||||||
|
@ -1,24 +1,7 @@
|
|||||||
//rule scheme :
|
//rule scheme :
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
shouldUseLocalResponse : function(req){
|
|
||||||
},
|
|
||||||
|
|
||||||
dealLocalResponse : function(req,callback){
|
|
||||||
},
|
|
||||||
|
|
||||||
replaceRequestOption : function(req,option){
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
replaceRequestProtocol:function(req,protocol){
|
|
||||||
},
|
|
||||||
|
|
||||||
replaceResponseStatusCode: function(req,res,statusCode){
|
|
||||||
},
|
|
||||||
|
|
||||||
replaceResponseHeader: function(req,res,header){
|
|
||||||
},
|
|
||||||
|
|
||||||
replaceServerResData: function(req,res,serverResData){
|
replaceServerResData: function(req,res,serverResData){
|
||||||
//add "hello github" to all github pages
|
//add "hello github" to all github pages
|
||||||
@ -28,9 +11,6 @@ module.exports = {
|
|||||||
return serverResData;
|
return serverResData;
|
||||||
},
|
},
|
||||||
|
|
||||||
pauseBeforeSendingResponse : function(req,res){
|
|
||||||
},
|
|
||||||
|
|
||||||
shouldInterceptHttpsReq :function(req){
|
shouldInterceptHttpsReq :function(req){
|
||||||
//intercept https://github.com/
|
//intercept https://github.com/
|
||||||
//otherwise, all the https traffic will not go through this proxy
|
//otherwise, all the https traffic will not go through this proxy
|
||||||
|
@ -1,21 +1,6 @@
|
|||||||
//rule scheme :
|
//rule scheme :
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
shouldUseLocalResponse : function(req){
|
|
||||||
},
|
|
||||||
|
|
||||||
dealLocalResponse : function(req,callback){
|
|
||||||
},
|
|
||||||
|
|
||||||
replaceRequestOption : function(req,option){
|
|
||||||
},
|
|
||||||
|
|
||||||
replaceRequestProtocol:function(req,protocol){
|
|
||||||
},
|
|
||||||
|
|
||||||
replaceResponseStatusCode: function(req,res,statusCode){
|
|
||||||
},
|
|
||||||
|
|
||||||
replaceResponseHeader: function(req,res,header){
|
replaceResponseHeader: function(req,res,header){
|
||||||
header = header || {};
|
header = header || {};
|
||||||
header["Cache-Control"] = "no-cache, no-store, must-revalidate";
|
header["Cache-Control"] = "no-cache, no-store, must-revalidate";
|
||||||
@ -23,17 +8,7 @@ module.exports = {
|
|||||||
header["Expires"] = 0;
|
header["Expires"] = 0;
|
||||||
|
|
||||||
return header;
|
return header;
|
||||||
},
|
|
||||||
|
|
||||||
replaceServerResData: function(req,res,serverResData){
|
|
||||||
},
|
|
||||||
|
|
||||||
pauseBeforeSendingResponse : function(req,res){
|
|
||||||
},
|
|
||||||
|
|
||||||
shouldInterceptHttpsReq :function(req){
|
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function disableCacheHeader(header){
|
function disableCacheHeader(header){
|
||||||
|
@ -1,11 +1,6 @@
|
|||||||
//rule scheme :
|
//rule scheme :
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
shouldUseLocalResponse : function(req){
|
|
||||||
},
|
|
||||||
|
|
||||||
dealLocalResponse : function(req,callback){
|
|
||||||
},
|
|
||||||
|
|
||||||
replaceRequestOption : function(req,option){
|
replaceRequestOption : function(req,option){
|
||||||
//replace request towards http://www.taobao.com
|
//replace request towards http://www.taobao.com
|
||||||
@ -24,25 +19,5 @@ module.exports = {
|
|||||||
if(option.hostname == "www.taobao.com" && option.path == "/"){
|
if(option.hostname == "www.taobao.com" && option.path == "/"){
|
||||||
option.path = "/about/";
|
option.path = "/about/";
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(option);
|
|
||||||
},
|
|
||||||
|
|
||||||
replaceRequestProtocol:function(req,protocol){
|
|
||||||
},
|
|
||||||
|
|
||||||
replaceResponseStatusCode: function(req,res,statusCode){
|
|
||||||
},
|
|
||||||
|
|
||||||
replaceResponseHeader: function(req,res,header){
|
|
||||||
},
|
|
||||||
|
|
||||||
replaceServerResData: function(req,res,serverResData){
|
|
||||||
},
|
|
||||||
|
|
||||||
pauseBeforeSendingResponse : function(req,res){
|
|
||||||
},
|
|
||||||
|
|
||||||
shouldInterceptHttpsReq :function(req){
|
|
||||||
}
|
}
|
||||||
};
|
};
|
@ -1,24 +1,6 @@
|
|||||||
//rule scheme :
|
//rule scheme :
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
shouldUseLocalResponse : function(req){
|
|
||||||
},
|
|
||||||
|
|
||||||
dealLocalResponse : function(req,callback){
|
|
||||||
},
|
|
||||||
|
|
||||||
replaceRequestOption : function(req,option){
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
replaceRequestProtocol:function(req,protocol){
|
|
||||||
},
|
|
||||||
|
|
||||||
replaceResponseStatusCode: function(req,res,statusCode){
|
|
||||||
},
|
|
||||||
|
|
||||||
replaceResponseHeader: function(req,res,header){
|
|
||||||
},
|
|
||||||
|
|
||||||
replaceServerResData: function(req,res,serverResData){
|
replaceServerResData: function(req,res,serverResData){
|
||||||
|
|
||||||
@ -31,11 +13,5 @@ module.exports = {
|
|||||||
return serverResData;
|
return serverResData;
|
||||||
}
|
}
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
pauseBeforeSendingResponse : function(req,res){
|
|
||||||
},
|
|
||||||
|
|
||||||
shouldInterceptHttpsReq :function(req){
|
|
||||||
}
|
}
|
||||||
};
|
};
|
@ -1,18 +1,6 @@
|
|||||||
//rule scheme :
|
//rule scheme :
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
shouldUseLocalResponse : function(req){
|
|
||||||
},
|
|
||||||
|
|
||||||
dealLocalResponse : function(req,callback){
|
|
||||||
},
|
|
||||||
|
|
||||||
replaceRequestOption : function(req,option){
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
replaceRequestProtocol:function(req,protocol){
|
|
||||||
},
|
|
||||||
|
|
||||||
replaceResponseStatusCode: function(req,res,statusCode){
|
replaceResponseStatusCode: function(req,res,statusCode){
|
||||||
//redirect requests toward http://www.taobao.com/*
|
//redirect requests toward http://www.taobao.com/*
|
||||||
@ -32,14 +20,5 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return header;
|
return header;
|
||||||
},
|
|
||||||
|
|
||||||
replaceServerResData: function(req,res,serverResData){
|
|
||||||
},
|
|
||||||
|
|
||||||
pauseBeforeSendingResponse : function(req,res){
|
|
||||||
},
|
|
||||||
|
|
||||||
shouldInterceptHttpsReq :function(req){
|
|
||||||
}
|
}
|
||||||
};
|
};
|
@ -1,9 +1,9 @@
|
|||||||
//replace all the images with local one
|
//replace all the images with local one
|
||||||
|
|
||||||
var url = require("url"),
|
var url = require("url"),
|
||||||
path = require("path"),
|
path = require("path"),
|
||||||
fs = require("fs"),
|
fs = require("fs"),
|
||||||
buffer = require("buffer");
|
buffer = require("buffer");
|
||||||
|
|
||||||
var map = [
|
var map = [
|
||||||
{
|
{
|
||||||
@ -15,7 +15,7 @@ var map = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
shouldUseLocalResponse : function(req){
|
shouldUseLocalResponse : function(req,reqBody){
|
||||||
var host = req.headers.host,
|
var host = req.headers.host,
|
||||||
urlPattern = url.parse(req.url),
|
urlPattern = url.parse(req.url),
|
||||||
path = urlPattern.path;
|
path = urlPattern.path;
|
||||||
@ -45,31 +45,10 @@ module.exports = {
|
|||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
|
|
||||||
dealLocalResponse : function(req,callback){
|
dealLocalResponse : function(req,reqBody,callback){
|
||||||
if(req.replaceLocalFile){
|
if(req.replaceLocalFile){
|
||||||
callback(200, {"content-type":"image/png"}, fs.readFileSync(req.replaceLocalFile) );
|
callback(200, {"content-type":"image/png"}, fs.readFileSync(req.replaceLocalFile) );
|
||||||
}
|
}
|
||||||
},
|
|
||||||
|
|
||||||
replaceRequestOption : function(req,option){
|
|
||||||
},
|
|
||||||
|
|
||||||
replaceRequestProtocol:function(req,protocol){
|
|
||||||
},
|
|
||||||
|
|
||||||
replaceResponseStatusCode: function(req,res,statusCode){
|
|
||||||
},
|
|
||||||
|
|
||||||
replaceResponseHeader: function(req,res,header){
|
|
||||||
},
|
|
||||||
|
|
||||||
replaceServerResData: function(req,res,serverResData){
|
|
||||||
},
|
|
||||||
|
|
||||||
pauseBeforeSendingResponse : function(req,res){
|
|
||||||
},
|
|
||||||
|
|
||||||
shouldInterceptHttpsReq :function(req){
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -13,6 +13,10 @@
|
|||||||
margin: 0 5px;
|
margin: 0 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.topHead .btn_disable{
|
||||||
|
color: #777;
|
||||||
|
}
|
||||||
|
|
||||||
.mainTableWrapper{
|
.mainTableWrapper{
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,8 @@
|
|||||||
<div class="topHead">
|
<div class="topHead">
|
||||||
<h1>Anyproxy</h1>
|
<h1>Anyproxy</h1>
|
||||||
<a href="#" class="J_clearBtn"><span class="topBtn">Clear Logs(Ctrl+X)</span></a>
|
<a href="#" class="J_clearBtn"><span class="topBtn">Clear Logs(Ctrl+X)</span></a>
|
||||||
|
<a href="#" class="J_statusBtn"><span class="topBtn">Stop</span></a>
|
||||||
|
<a href="#" class="J_statusBtn btn_disable"><span class="topBtn">Resume</span></a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mainTableWrapper J_mainTable">
|
<div class="mainTableWrapper J_mainTable">
|
||||||
@ -58,6 +60,13 @@
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
<section class="reqBody">
|
||||||
|
<h4 class="subTitle">request body</h4>
|
||||||
|
<div class="detail">
|
||||||
|
<p><%= reqBody %></p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
<% if(statusCode) { %>
|
<% if(statusCode) { %>
|
||||||
<section class="resHeader">
|
<section class="resHeader">
|
||||||
<h4 class="subTitle">response header</h4>
|
<h4 class="subTitle">response header</h4>
|
||||||
|
29
web/page.js
29
web/page.js
@ -13,7 +13,6 @@ seajs.use(['$','Underscore' ,'Backbone'], function($, _, Backbone) {
|
|||||||
$(function(){
|
$(function(){
|
||||||
|
|
||||||
//record detail
|
//record detail
|
||||||
//backbone太麻烦了,这里手写拉倒..
|
|
||||||
var DetailView = function(){
|
var DetailView = function(){
|
||||||
var self = this,
|
var self = this,
|
||||||
$detailEl = $(".J_recordDetailOverlay"),
|
$detailEl = $(".J_recordDetailOverlay"),
|
||||||
@ -153,13 +152,35 @@ seajs.use(['$','Underscore' ,'Backbone'], function($, _, Backbone) {
|
|||||||
recList.reset();
|
recList.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//pause btn
|
||||||
|
var ifPause = false;
|
||||||
|
(function(){
|
||||||
|
var statusBtn = $(".J_statusBtn");
|
||||||
|
statusBtn.on("click",function(e){
|
||||||
|
e.stopPropagation();
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
$(".J_statusBtn").removeClass("btn_disable");
|
||||||
|
$(this).addClass("btn_disable");
|
||||||
|
|
||||||
|
if(/stop/i.test($(this).html()) ){
|
||||||
|
ifPause = true;
|
||||||
|
}else{
|
||||||
|
ifPause = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})();
|
||||||
|
|
||||||
//data via web socket
|
//data via web socket
|
||||||
var dataSocket = new WebSocket("ws://127.0.0.1:8003");
|
if(!WebSocket){
|
||||||
dataSocket.onopen = function(){
|
alert("WebSocket is required. Please use a modern browser.");
|
||||||
console.log("dataSocket open");
|
return;
|
||||||
}
|
}
|
||||||
|
var dataSocket = new WebSocket("ws://127.0.0.1:8003");
|
||||||
|
dataSocket.onopen = function(){}
|
||||||
|
|
||||||
dataSocket.onmessage = function(event){
|
dataSocket.onmessage = function(event){
|
||||||
|
if(ifPause) return;
|
||||||
var data = JSON.parse(event.data);
|
var data = JSON.parse(event.data);
|
||||||
|
|
||||||
var reqDate = new Date(data.startTime);
|
var reqDate = new Date(data.startTime);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user