mirror of
https://github.com/alibaba/anyproxy.git
synced 2025-04-24 04:01:27 +00:00
reconstruct map local
This commit is contained in:
parent
b595e3aa9c
commit
8a146f7373
@ -1,6 +1,13 @@
|
||||
var utils = require("./util"),
|
||||
bodyParser = require("body-parser"),
|
||||
fs = require("fs");
|
||||
|
||||
var isRootCAFileExists = require("./certMgr.js").isRootCAFileExists(),
|
||||
interceptFlag = false;
|
||||
|
||||
//e.g. [ { keyword: 'aaa', local: '/Users/Stella/061739.pdf' } ]
|
||||
var mapConfig = [];
|
||||
|
||||
module.exports = {
|
||||
summary:function(){
|
||||
var tip = "the default rule for anyproxy which supports CORS. ";
|
||||
@ -15,13 +22,30 @@ module.exports = {
|
||||
if(req.method == "OPTIONS"){
|
||||
return true;
|
||||
}else{
|
||||
var simpleUrl = (req.headers.host || "") + (req.url || "");
|
||||
mapConfig.map(function(item){
|
||||
var key = item.keyword;
|
||||
if(simpleUrl.indexOf(key) >= 0){
|
||||
req.anyproxy_map_local = item.local;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
return !!req.anyproxy_map_local;
|
||||
}
|
||||
},
|
||||
|
||||
dealLocalResponse : function(req,reqBody,callback){
|
||||
if(req.method == "OPTIONS"){
|
||||
callback(200,mergeCORSHeader(req.headers),"");
|
||||
}else if(req.anyproxy_map_local){
|
||||
try{
|
||||
var fileContent = fs.readFile(req.anyproxy_map_local,function(err,buffer){
|
||||
callback(200, {}, buffer);
|
||||
});
|
||||
}catch(e){
|
||||
callback(200, {}, "failed to load local file :" + req.anyproxy_map_local);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@ -63,6 +87,31 @@ module.exports = {
|
||||
|
||||
setInterceptFlag: function(flag){
|
||||
interceptFlag = flag && isRootCAFileExists;
|
||||
},
|
||||
|
||||
_plugIntoWebinterface: function(app,cb){
|
||||
|
||||
app.get("/filetree",function(req,res){
|
||||
try{
|
||||
var root = req.query.root || process.env.HOME || "/";
|
||||
utils.filewalker(root,function(err, info){
|
||||
res.json(info);
|
||||
});
|
||||
}catch(e){
|
||||
res.end(e);
|
||||
}
|
||||
});
|
||||
|
||||
app.use(bodyParser.json());
|
||||
app.get("/getMapConfig",function(req,res){
|
||||
res.json(mapConfig);
|
||||
});
|
||||
app.post("/setMapConfig",function(req,res){
|
||||
mapConfig = req.body;
|
||||
res.json(mapConfig);
|
||||
});
|
||||
|
||||
cb();
|
||||
}
|
||||
|
||||
};
|
||||
|
37
lib/util.js
37
lib/util.js
@ -1,3 +1,6 @@
|
||||
var fs = require("fs"),
|
||||
path = require("path");
|
||||
|
||||
// {"Content-Encoding":"gzip"} --> {"content-encoding":"gzip"}
|
||||
module.exports.lower_keys = function(obj){
|
||||
for(var key in obj){
|
||||
@ -27,5 +30,37 @@ module.exports.simpleRender = function(str, object, regexp){
|
||||
if (match.charAt(0) == '\\') return match.slice(1);
|
||||
return (object[name] != null) ? object[name] : '';
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
module.exports.filewalker = function(root,cb){
|
||||
root = root || process.cwd();
|
||||
|
||||
var ret = {
|
||||
directory :[],
|
||||
file :[]
|
||||
};
|
||||
|
||||
fs.readdir(root,function(err, list){
|
||||
if(list && list.length){
|
||||
list.map(function(item){
|
||||
var fullPath = path.join(root,item),
|
||||
stat = fs.lstatSync(fullPath);
|
||||
|
||||
if(stat.isFile()){
|
||||
ret.file.push({
|
||||
name : item,
|
||||
fullPath : fullPath
|
||||
});
|
||||
|
||||
}else if(stat.isDirectory()){
|
||||
ret.directory.push({
|
||||
name : item,
|
||||
fullPath : fullPath
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
cb && cb.apply(null,[null,ret]);
|
||||
});
|
||||
}
|
||||
|
@ -14,8 +14,13 @@ var express = require("express"),
|
||||
function webInterface(config){
|
||||
var port = config.port,
|
||||
wsPort = config.wsPort,
|
||||
ruleSummary = config.ruleSummary,
|
||||
ipAddress = config.ip;
|
||||
ipAddress = config.ip,
|
||||
userRule = config.userRule,
|
||||
ruleSummary = "";
|
||||
|
||||
try{
|
||||
ruleSummary = userRule.summary();
|
||||
}catch(e){}
|
||||
|
||||
var self = this,
|
||||
myAbsAddress = "http://" + ipAddress + ":" + port +"/",
|
||||
@ -81,8 +86,6 @@ function webInterface(config){
|
||||
res.end(resDom);
|
||||
});
|
||||
|
||||
|
||||
|
||||
app.use(function(req,res,next){
|
||||
var indexTpl = fs.readFileSync(path.join(staticDir,"/index.html"),{encoding:"utf8"}),
|
||||
indexHTML = util.simpleRender(indexTpl, {
|
||||
@ -100,7 +103,14 @@ function webInterface(config){
|
||||
});
|
||||
|
||||
app.use(express.static(staticDir));
|
||||
|
||||
if(typeof userRule._plugIntoWebinterface == "function"){
|
||||
userRule._plugIntoWebinterface(app,function(){
|
||||
app.listen(port);
|
||||
});
|
||||
}else{
|
||||
app.listen(port);
|
||||
}
|
||||
|
||||
self.app = app;
|
||||
}
|
||||
|
@ -9,6 +9,7 @@
|
||||
"dependencies": {
|
||||
"async": "~0.9.0",
|
||||
"async-task-mgr": ">=1.1.0",
|
||||
"body-parser": "^1.13.1",
|
||||
"colorful": "^2.1.0",
|
||||
"commander": "~2.3.0",
|
||||
"compression": "^1.4.4",
|
||||
|
2
proxy.js
2
proxy.js
@ -157,7 +157,7 @@ function proxyServer(option){
|
||||
var config = {
|
||||
port : proxyWebPort,
|
||||
wsPort : socketPort,
|
||||
ruleSummary : requestHandler.getRuleSummary(),
|
||||
userRule : proxyRules,
|
||||
ip : ip.address()
|
||||
};
|
||||
|
||||
|
@ -1,88 +1,25 @@
|
||||
function init(React){
|
||||
|
||||
function dragableBar(initX,cb){
|
||||
var self = this,
|
||||
dragging = true;
|
||||
|
||||
var ghostbar = $('<div class="ghostbar"></div>').css("left",initX).prependTo('body');
|
||||
|
||||
$(document).mousemove(function(e){
|
||||
e.preventDefault();
|
||||
ghostbar.css("left",e.pageX + "px");
|
||||
});
|
||||
|
||||
$(document).mouseup(function(e){
|
||||
if(!dragging) return;
|
||||
|
||||
dragging = false;
|
||||
|
||||
var deltaPageX = e.pageX - initX;
|
||||
cb && cb.call(null,{
|
||||
delta : deltaPageX,
|
||||
finalX : e.pageX
|
||||
});
|
||||
|
||||
ghostbar.remove();
|
||||
$(document).unbind('mousemove');
|
||||
});
|
||||
}
|
||||
|
||||
var DetailPanel = React.createClass({displayName: "DetailPanel",
|
||||
getInitialState : function(){
|
||||
return {
|
||||
show : false,
|
||||
data : {},
|
||||
body : {id : -1, content : null},
|
||||
left : "35%"
|
||||
};
|
||||
},
|
||||
componentDidMount:function(){
|
||||
var self = this;
|
||||
$(document).on("keyup",function(e){
|
||||
if(e.keyCode == 27){ //ESC
|
||||
self.setState({
|
||||
show : false
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
setHide:function(){
|
||||
this.setState({
|
||||
show : false
|
||||
});
|
||||
},
|
||||
setShow:function(ifShow){
|
||||
this.setState({
|
||||
show : true
|
||||
});
|
||||
},
|
||||
loadBody:function(){
|
||||
var self = this,
|
||||
id = self.state.data.id;
|
||||
id = self.props.data.id;
|
||||
if(!id) return;
|
||||
|
||||
ws.reqBody(id,function(content){
|
||||
if(content.id == self.state.data.id){
|
||||
if(content.id == self.props.data.id){
|
||||
self.setState({
|
||||
body : content
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
dealDrag:function(){
|
||||
var self = this,
|
||||
leftVal = $(React.findDOMNode(this.refs.mainOverlay)).css("left");
|
||||
dragableBar(leftVal, function(data){
|
||||
if(data && data.finalX){
|
||||
if(window.innerWidth - data.finalX < 200){
|
||||
data.finalX = window.innerWidth - 200;
|
||||
}
|
||||
self.setState({
|
||||
left : data.finalX + "px"
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
render : function(){
|
||||
var reqHeaderSection = [],
|
||||
resHeaderSection = [],
|
||||
@ -90,9 +27,9 @@ function init(React){
|
||||
detailSection,
|
||||
bodyContent;
|
||||
|
||||
if(this.state.data.reqHeader){
|
||||
for(var key in this.state.data.reqHeader){
|
||||
reqHeaderSection.push(React.createElement("li", {key: "reqHeader_" + key}, React.createElement("strong", null, key), " : ", this.state.data.reqHeader[key]))
|
||||
if(this.props.data.reqHeader){
|
||||
for(var key in this.props.data.reqHeader){
|
||||
reqHeaderSection.push(React.createElement("li", {key: "reqHeader_" + key}, React.createElement("strong", null, key), " : ", this.props.data.reqHeader[key]))
|
||||
}
|
||||
}
|
||||
|
||||
@ -102,7 +39,7 @@ function init(React){
|
||||
React.createElement("h4", {className: "subTitle"}, "request"),
|
||||
React.createElement("div", {className: "detail"},
|
||||
React.createElement("ul", {className: "uk-list"},
|
||||
React.createElement("li", null, this.state.data.method, " ", React.createElement("span", {title: "{this.state.data.path}"}, this.state.data.path), " HTTP/1.1"),
|
||||
React.createElement("li", null, this.props.data.method, " ", React.createElement("span", {title: "{this.props.data.path}"}, this.props.data.path), " HTTP/1.1"),
|
||||
reqHeaderSection
|
||||
)
|
||||
)
|
||||
@ -111,24 +48,24 @@ function init(React){
|
||||
React.createElement("section", {className: "reqBody"},
|
||||
React.createElement("h4", {className: "subTitle"}, "request body"),
|
||||
React.createElement("div", {className: "detail"},
|
||||
React.createElement("p", null, this.state.data.reqBody)
|
||||
React.createElement("p", null, this.props.data.reqBody)
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
if(this.state.data.statusCode){
|
||||
if(this.props.data.statusCode){
|
||||
|
||||
if(this.state.body.id == this.state.data.id){
|
||||
if(this.state.body.id == this.props.data.id){
|
||||
bodyContent = (React.createElement("pre", {className: "resBodyContent"}, this.state.body.body));
|
||||
}else{
|
||||
bodyContent = null;
|
||||
this.loadBody();
|
||||
}
|
||||
|
||||
if(this.state.data.resHeader){
|
||||
for(var key in this.state.data.resHeader){
|
||||
resHeaderSection.push(React.createElement("li", {key: "resHeader_" + key}, React.createElement("strong", null, key), " : ", this.state.data.resHeader[key]))
|
||||
if(this.props.data.resHeader){
|
||||
for(var key in this.props.data.resHeader){
|
||||
resHeaderSection.push(React.createElement("li", {key: "resHeader_" + key}, React.createElement("strong", null, key), " : ", this.props.data.resHeader[key]))
|
||||
}
|
||||
}
|
||||
|
||||
@ -138,7 +75,7 @@ function init(React){
|
||||
React.createElement("h4", {className: "subTitle"}, "response header"),
|
||||
React.createElement("div", {className: "detail"},
|
||||
React.createElement("ul", {className: "uk-list"},
|
||||
React.createElement("li", null, "HTTP/1.1 ", React.createElement("span", {className: "http_status http_status_" + this.state.data.statusCode}, this.state.data.statusCode)),
|
||||
React.createElement("li", null, "HTTP/1.1 ", React.createElement("span", {className: "http_status http_status_" + this.props.data.statusCode}, this.props.data.statusCode)),
|
||||
resHeaderSection
|
||||
)
|
||||
)
|
||||
@ -153,17 +90,10 @@ function init(React){
|
||||
}
|
||||
|
||||
return (
|
||||
React.createElement("div", {style: {display:this.state.show ? "block" :"none"}},
|
||||
React.createElement("div", {className: "overlay_mask", onClick: this.setHide}),
|
||||
React.createElement("div", {className: "recordDetailOverlay", ref: "mainOverlay", style: {left: this.state.left}},
|
||||
React.createElement("div", {className: "dragbar", onMouseDown: this.dealDrag}),
|
||||
React.createElement("span", {className: "escBtn", onClick: this.setHide}, "Close (ESC)"),
|
||||
React.createElement("div", null,
|
||||
summarySection,
|
||||
detailSection
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
});
|
||||
|
39
web/build/filter.js
Normal file
39
web/build/filter.js
Normal file
@ -0,0 +1,39 @@
|
||||
function init(React){
|
||||
|
||||
var Filter = React.createClass({displayName: "Filter",
|
||||
|
||||
dealChange:function(){
|
||||
var self = this,
|
||||
userInput = React.findDOMNode(self.refs.keywordInput).value;
|
||||
|
||||
self.props.onChangeKeyword && self.props.onChangeKeyword.call(null,userInput);
|
||||
},
|
||||
setFocus:function(){
|
||||
var self = this;
|
||||
React.findDOMNode(self.refs.keywordInput).focus();
|
||||
},
|
||||
componentDidUpdate:function(){
|
||||
this.setFocus();
|
||||
},
|
||||
render:function(){
|
||||
var self = this;
|
||||
|
||||
return (
|
||||
React.createElement("div", {className: "filterSection"},
|
||||
React.createElement("h4", {className: "subTitle"}, "Log Filter"),
|
||||
|
||||
React.createElement("form", {className: "uk-form"},
|
||||
React.createElement("input", {className: "uk-form-large", ref: "keywordInput", onChange: self.dealChange, type: "text", placeholder: "type keywords or /^regExp$/", width: "300"})
|
||||
)
|
||||
)
|
||||
);
|
||||
},
|
||||
componentDidMount:function(){
|
||||
this.setFocus();
|
||||
}
|
||||
});
|
||||
|
||||
return Filter;
|
||||
}
|
||||
|
||||
module.exports.init = init;
|
@ -1,10 +1,15 @@
|
||||
require("../lib/zepto");
|
||||
window.$ = window.jQuery = require("../lib/jquery");
|
||||
|
||||
var EventManager = require('../lib/event'),
|
||||
Anyproxy_wsUtil = require("../lib/anyproxy_wsUtil"),
|
||||
React = require("../lib/react");
|
||||
|
||||
var WsIndicator = require("./wsIndicator").init(React),
|
||||
RecordPanel = require("./recordPanel").init(React);
|
||||
RecordPanel = require("./recordPanel").init(React),
|
||||
MapPanel = require("./mapPanel").init(React),
|
||||
Detail = require("./detailPanel").init(React),
|
||||
Popup = require("./popup").init(React),
|
||||
Filter = require("./filter").init(React);
|
||||
|
||||
var ifPause = false,
|
||||
recordSet = [];
|
||||
@ -15,6 +20,7 @@ var ifPause = false,
|
||||
//Event : wsEnd
|
||||
var eventCenter = new EventManager();
|
||||
|
||||
|
||||
//invoke AnyProxy web socket util
|
||||
(function(){
|
||||
try{
|
||||
@ -63,7 +69,19 @@ var eventCenter = new EventManager();
|
||||
})();
|
||||
|
||||
|
||||
//record panel
|
||||
//init popup
|
||||
var pop;
|
||||
(function(){
|
||||
$("body").append('<div id="J_popOuter"></div>');
|
||||
pop = React.render(
|
||||
React.createElement(Popup, null),
|
||||
document.getElementById("J_popOuter")
|
||||
);
|
||||
})();
|
||||
|
||||
|
||||
//init record panel
|
||||
var recorder;
|
||||
(function(){
|
||||
//merge : right --> left
|
||||
function util_merge(left,right){
|
||||
@ -89,29 +107,40 @@ var eventCenter = new EventManager();
|
||||
// React.addons.Perf.stop();
|
||||
}
|
||||
}
|
||||
|
||||
function showDetail(data){
|
||||
pop.setState({
|
||||
show: true,
|
||||
content : React.createElement(Detail, {data: data}),
|
||||
left:"35%"
|
||||
});
|
||||
}
|
||||
|
||||
eventCenter.addListener("wsGetUpdate",updateRecordSet);
|
||||
|
||||
var Panel = React.render(
|
||||
React.createElement(RecordPanel, null),
|
||||
document.getElementById("J_content")
|
||||
);
|
||||
|
||||
eventCenter.addListener('recordSetUpdated',function(){
|
||||
Panel.setState({
|
||||
recorder.setState({
|
||||
list : recordSet
|
||||
});
|
||||
});
|
||||
|
||||
eventCenter.addListener("filterUpdated",function(newKeyword){
|
||||
Panel.setState({
|
||||
recorder.setState({
|
||||
filter: newKeyword
|
||||
});
|
||||
});
|
||||
|
||||
//init recorder panel
|
||||
recorder = React.render(
|
||||
React.createElement(RecordPanel, {onSelect: showDetail}),
|
||||
document.getElementById("J_content")
|
||||
);
|
||||
})();
|
||||
|
||||
|
||||
//action bar
|
||||
(function(){
|
||||
//clear log
|
||||
function clearLogs(){
|
||||
recordSet = [];
|
||||
eventCenter.dispatchEvent("recordSetUpdated");
|
||||
@ -130,6 +159,7 @@ var eventCenter = new EventManager();
|
||||
clearLogs();
|
||||
});
|
||||
|
||||
//start , pause
|
||||
var statusBtn = $(".J_statusBtn");
|
||||
statusBtn.on("click",function(e){
|
||||
e.stopPropagation();
|
||||
@ -145,26 +175,41 @@ var eventCenter = new EventManager();
|
||||
}
|
||||
});
|
||||
|
||||
function switchFilterWidget(ifToShow){
|
||||
if(ifToShow){
|
||||
$(".J_filterSection").show();
|
||||
$("#J_filterKeyword").focus();
|
||||
}else{
|
||||
$(".J_filterSection").hide();
|
||||
$("#J_filterKeyword").val("");
|
||||
}
|
||||
//filter
|
||||
(function (){
|
||||
function updateKeyword(key){
|
||||
eventCenter.dispatchEvent("filterUpdated",key);
|
||||
}
|
||||
|
||||
$(".J_toggleFilterBtn").on("click",function(){
|
||||
switchFilterWidget( $(".J_filterSection").css("display") == "none" );
|
||||
var filter = (React.createElement(Filter, {onChangeKeyword: updateKeyword}));
|
||||
function showFilter(){
|
||||
pop.setState({
|
||||
show : true,
|
||||
content : filter,
|
||||
left:"70%"
|
||||
});
|
||||
}
|
||||
|
||||
$(".J_filterCloseBtn").on("click",function(){
|
||||
switchFilterWidget(false);
|
||||
});
|
||||
|
||||
|
||||
$("#J_filterKeyword").on("change keyup",function(){
|
||||
eventCenter.dispatchEvent("filterUpdated",this.value);
|
||||
$(".J_showFilter").on("click",function(){
|
||||
showFilter();
|
||||
});
|
||||
})();
|
||||
|
||||
//map local
|
||||
(function(){
|
||||
var mapPanel = (React.createElement(MapPanel, null));
|
||||
function showMap(){
|
||||
pop.setState({
|
||||
show : true,
|
||||
content : mapPanel,
|
||||
left:"70%"
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
$(".J_showMapPanel").on("click",function(){
|
||||
showMap();
|
||||
});
|
||||
})();
|
||||
|
||||
})();
|
114
web/build/mapForm.js
Normal file
114
web/build/mapForm.js
Normal file
@ -0,0 +1,114 @@
|
||||
require("../lib/jstree");
|
||||
|
||||
function init(React){
|
||||
function fetchTree(root,cb){
|
||||
if(!root || root == "#"){
|
||||
root = "";
|
||||
}
|
||||
|
||||
$.getJSON("/filetree?root=" + root,function(resObj){
|
||||
var ret = [];
|
||||
try{
|
||||
$.each(resObj.directory, function(k,item){
|
||||
if(item.name.indexOf(".") == 0) return;
|
||||
ret.push({
|
||||
text : item.name,
|
||||
id : item.fullPath,
|
||||
icon : "uk-icon-folder",
|
||||
children : true
|
||||
});
|
||||
});
|
||||
|
||||
$.each(resObj.file, function(k,item){
|
||||
if(item.name.indexOf(".") == 0) return;
|
||||
ret.push({
|
||||
text : item.name,
|
||||
id : item.fullPath,
|
||||
icon : 'uk-icon-file-o',
|
||||
children : false
|
||||
});
|
||||
});
|
||||
}catch(e){}
|
||||
cb && cb.call(null,ret);
|
||||
});
|
||||
}
|
||||
|
||||
var MapForm = React.createClass({displayName: "MapForm",
|
||||
|
||||
submitData:function(){
|
||||
var self = this,
|
||||
result = {};
|
||||
|
||||
var filePath = React.findDOMNode(self.refs.localFilePath).value,
|
||||
keyword = React.findDOMNode(self.refs.keywordInput).value;
|
||||
|
||||
if(filePath && keyword){
|
||||
self.props.onSubmit.call(null,{
|
||||
keyword : keyword,
|
||||
local : filePath
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
render:function(){
|
||||
var self = this;
|
||||
return (
|
||||
React.createElement("div", null,
|
||||
React.createElement("form", {className: "uk-form uk-form-stacked"},
|
||||
React.createElement("fieldset", null,
|
||||
React.createElement("legend", null, "add rule"),
|
||||
|
||||
React.createElement("div", {className: "uk-form-row"},
|
||||
React.createElement("label", {className: "uk-form-label", htmlFor: "map_keywordInput"}, "keyword"),
|
||||
React.createElement("div", {className: "uk-form-controls"},
|
||||
React.createElement("input", {type: "text", id: "map_keywordInput", ref: "keywordInput", placeholder: "keyword"})
|
||||
)
|
||||
),
|
||||
|
||||
React.createElement("div", {className: "uk-form-row"},
|
||||
React.createElement("label", {className: "uk-form-label", htmlFor: "map_localFilePath"}, "local file"),
|
||||
React.createElement("div", {className: "uk-form-controls"},
|
||||
React.createElement("input", {type: "text", id: "map_localFilePath", ref: "localFilePath", placeholder: "keyword"})
|
||||
)
|
||||
)
|
||||
|
||||
)
|
||||
),
|
||||
|
||||
React.createElement("div", {ref: "treeWrapper"}),
|
||||
React.createElement("button", {className: "uk-button", onClick: self.submitData}, "Add")
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
componentDidMount :function(){
|
||||
var self = this;
|
||||
var wrapperEl = $(React.findDOMNode(self.refs.treeWrapper)),
|
||||
filePathInput = React.findDOMNode(self.refs.localFilePath);
|
||||
|
||||
wrapperEl.jstree({
|
||||
'core' : {
|
||||
'data' : function (node, cb) {
|
||||
fetchTree(node.id,cb);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
wrapperEl.on("changed.jstree", function (e, data) {
|
||||
if(data && data.selected && data.selected.length){
|
||||
//is folder
|
||||
if(/folder/.test(data.node.icon)) return;
|
||||
|
||||
var item = data.selected[0];
|
||||
filePathInput.value = item;
|
||||
}
|
||||
});
|
||||
|
||||
},
|
||||
componentDidUpdate:function(){}
|
||||
});
|
||||
|
||||
return MapForm;
|
||||
}
|
||||
|
||||
module.exports.init = init;
|
80
web/build/mapList.js
Normal file
80
web/build/mapList.js
Normal file
@ -0,0 +1,80 @@
|
||||
function init(React){
|
||||
var MapList = React.createClass({displayName: "MapList",
|
||||
getInitialState:function(){
|
||||
return {
|
||||
ruleList : []
|
||||
}
|
||||
},
|
||||
appendRecord:function(data){
|
||||
var self = this,
|
||||
newState = self.state.ruleList;
|
||||
|
||||
if(data && data.keyword && data.local){
|
||||
newState.push({
|
||||
keyword : data.keyword,
|
||||
local : data.local
|
||||
});
|
||||
|
||||
self.setState({
|
||||
ruleList: newState
|
||||
});
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
removeRecord:function(index){
|
||||
var self = this,
|
||||
newList = self.state.ruleList;
|
||||
|
||||
newList.splice(index,1);
|
||||
self.setState({
|
||||
ruleList : newList
|
||||
});
|
||||
},
|
||||
render:function(){
|
||||
var self = this,
|
||||
collection = [];
|
||||
|
||||
collection = self.state.ruleList.map(function(item,index){
|
||||
return (
|
||||
React.createElement("li", null,
|
||||
React.createElement("strong", null, item.keyword), React.createElement("a", {className: "removeBtn", href: "#", onClick: self.removeRecord.bind(self,index)}, "remove"), React.createElement("br", null),
|
||||
React.createElement("span", null, item.local)
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
return (
|
||||
React.createElement("ul", {className: "mapRuleList"},
|
||||
collection
|
||||
)
|
||||
);
|
||||
},
|
||||
componentDidMount :function(){
|
||||
var self = this;
|
||||
$.getJSON("/getMapConfig",function(data){
|
||||
self.setState({
|
||||
ruleList : data
|
||||
});
|
||||
});
|
||||
},
|
||||
componentDidUpdate:function(){
|
||||
var self = this;
|
||||
//sync config
|
||||
|
||||
var currentList = self.state.ruleList;
|
||||
$.ajax({
|
||||
method : "POST",
|
||||
url : "/setMapConfig",
|
||||
contentType :"application/json",
|
||||
data : JSON.stringify(currentList),
|
||||
dataType : "json",
|
||||
success :function(res){}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return MapList;
|
||||
}
|
||||
|
||||
module.exports.init = init;
|
32
web/build/mapPanel.js
Normal file
32
web/build/mapPanel.js
Normal file
@ -0,0 +1,32 @@
|
||||
require("../lib/jstree");
|
||||
|
||||
function init(React){
|
||||
var MapForm = require("./mapForm").init(React),
|
||||
MapList = require("./mapList").init(React);
|
||||
|
||||
var MapPanel = React.createClass({displayName: "MapPanel",
|
||||
appendRecord : function(data){
|
||||
var self = this,
|
||||
listComponent = self.refs.list;
|
||||
|
||||
listComponent.appendRecord(data);
|
||||
},
|
||||
|
||||
render:function(){
|
||||
var self = this;
|
||||
return (
|
||||
React.createElement("div", {className: "mapWrapper"},
|
||||
React.createElement("h4", {className: "subTitle"}, "Current Config"),
|
||||
React.createElement(MapList, {ref: "list"}),
|
||||
|
||||
React.createElement("h4", {className: "subTitle"}, "Map Local"),
|
||||
React.createElement(MapForm, {onSubmit: self.appendRecord})
|
||||
)
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
return MapPanel;
|
||||
}
|
||||
|
||||
module.exports.init = init;
|
94
web/build/popup.js
Normal file
94
web/build/popup.js
Normal file
@ -0,0 +1,94 @@
|
||||
function init(React){
|
||||
|
||||
function dragableBar(initX,cb){
|
||||
var self = this,
|
||||
dragging = true;
|
||||
|
||||
var ghostbar = $('<div class="ghostbar"></div>').css("left",initX).prependTo('body');
|
||||
|
||||
$(document).mousemove(function(e){
|
||||
e.preventDefault();
|
||||
ghostbar.css("left",e.pageX + "px");
|
||||
});
|
||||
|
||||
$(document).mouseup(function(e){
|
||||
if(!dragging) return;
|
||||
|
||||
dragging = false;
|
||||
|
||||
var deltaPageX = e.pageX - initX;
|
||||
cb && cb.call(null,{
|
||||
delta : deltaPageX,
|
||||
finalX : e.pageX
|
||||
});
|
||||
|
||||
ghostbar.remove();
|
||||
$(document).unbind('mousemove');
|
||||
});
|
||||
}
|
||||
|
||||
var Popup = React.createClass({displayName: "Popup",
|
||||
getInitialState : function(){
|
||||
return {
|
||||
show : false,
|
||||
left : "35%",
|
||||
content : null
|
||||
};
|
||||
},
|
||||
componentDidMount:function(){
|
||||
var self = this;
|
||||
$(document).on("keyup",function(e){
|
||||
if(e.keyCode == 27){ //ESC
|
||||
self.setState({
|
||||
show : false
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
setHide:function(){
|
||||
this.setState({
|
||||
show : false
|
||||
});
|
||||
},
|
||||
setShow:function(ifShow){
|
||||
this.setState({
|
||||
show : true
|
||||
});
|
||||
},
|
||||
dealDrag:function(){
|
||||
var self = this,
|
||||
leftVal = $(React.findDOMNode(this.refs.mainOverlay)).css("left");
|
||||
dragableBar(leftVal, function(data){
|
||||
if(data && data.finalX){
|
||||
if(window.innerWidth - data.finalX < 200){
|
||||
data.finalX = window.innerWidth - 200;
|
||||
}
|
||||
self.setState({
|
||||
left : data.finalX + "px"
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
componentDidUpdate:function(){
|
||||
|
||||
},
|
||||
render : function(){
|
||||
return (
|
||||
React.createElement("div", {style: {display:this.state.show ? "block" :"none"}},
|
||||
React.createElement("div", {className: "overlay_mask", onClick: this.setHide}),
|
||||
React.createElement("div", {className: "recordDetailOverlay", ref: "mainOverlay", style: {left: this.state.left}},
|
||||
React.createElement("div", {className: "dragbar", onMouseDown: this.dealDrag}),
|
||||
React.createElement("span", {className: "escBtn", onClick: this.setHide}, "Close (ESC)"),
|
||||
React.createElement("div", null,
|
||||
this.state.content
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
return Popup;
|
||||
}
|
||||
|
||||
module.exports.init = init;
|
@ -9,8 +9,9 @@ function init(React){
|
||||
};
|
||||
},
|
||||
render : function(){
|
||||
var rowCollection = [],
|
||||
filterStr = this.state.filter,
|
||||
var self = this,
|
||||
rowCollection = [],
|
||||
filterStr = self.state.filter,
|
||||
filter = filterStr;
|
||||
|
||||
//regexp
|
||||
@ -20,8 +21,8 @@ function init(React){
|
||||
}catch(e){}
|
||||
}
|
||||
|
||||
for(var i = this.state.list.length-1 ; i >=0 ; i--){
|
||||
var item = this.state.list[i];
|
||||
for(var i = self.state.list.length-1 ; i >=0 ; i--){
|
||||
var item = self.state.list[i];
|
||||
if(item){
|
||||
if(filter && item){
|
||||
try{
|
||||
@ -40,7 +41,7 @@ function init(React){
|
||||
item._needRender = false;
|
||||
}
|
||||
|
||||
rowCollection.push(React.createElement(RecordRow, {key: item.id, data: item}));
|
||||
rowCollection.push(React.createElement(RecordRow, {key: item.id, data: item, onSelect: self.props.onSelect.bind(self,item)}));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,12 +1,4 @@
|
||||
function init(React){
|
||||
var DetailPanel = require("./detailPanel").init(React);
|
||||
|
||||
$("body").append('<div id="J_detailPanel"></div>');
|
||||
var detail = React.render(
|
||||
React.createElement(DetailPanel, null),
|
||||
document.getElementById("J_detailPanel")
|
||||
);
|
||||
|
||||
function dateFormat(date,fmt) {
|
||||
var o = {
|
||||
"M+": date.getMonth() + 1, //月份
|
||||
@ -26,12 +18,6 @@ function init(React){
|
||||
getInitialState : function(){
|
||||
return null;
|
||||
},
|
||||
handleClick:function(e){
|
||||
detail.setState({
|
||||
data : this.props.data,
|
||||
show : true
|
||||
});
|
||||
},
|
||||
render : function(){
|
||||
var trClassesArr = [],
|
||||
trClasses;
|
||||
@ -45,7 +31,7 @@ function init(React){
|
||||
var dateStr = dateFormat(new Date(this.props.data.startTime),"hh:mm:ss");
|
||||
|
||||
return(
|
||||
React.createElement("tr", {className: trClasses, onClick: this.handleClick},
|
||||
React.createElement("tr", {className: trClasses, onClick: this.props.onSelect},
|
||||
React.createElement("td", {className: "data_id"}, this.props.data._id),
|
||||
React.createElement("td", null, this.props.data.method, " ", React.createElement("span", {className: "protocol protocol_" + this.props.data.protocol, title: "https"}, React.createElement("i", {className: "uk-icon-lock"})), " "),
|
||||
React.createElement("td", {className: "http_status http_status_" + this.props.data.statusCode}, this.props.data.statusCode),
|
||||
@ -64,7 +50,6 @@ function init(React){
|
||||
});
|
||||
|
||||
return RecordRow;
|
||||
|
||||
}
|
||||
|
||||
module.exports.init = init;
|
BIN
web/css/jstree_style/32px.png
Executable file
BIN
web/css/jstree_style/32px.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 3.0 KiB |
BIN
web/css/jstree_style/40px.png
Executable file
BIN
web/css/jstree_style/40px.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 1.8 KiB |
1031
web/css/jstree_style/style.css
Executable file
1031
web/css/jstree_style/style.css
Executable file
File diff suppressed because it is too large
Load Diff
1
web/css/jstree_style/style.min.css
vendored
Executable file
1
web/css/jstree_style/style.min.css
vendored
Executable file
File diff suppressed because one or more lines are too long
BIN
web/css/jstree_style/throbber.gif
Executable file
BIN
web/css/jstree_style/throbber.gif
Executable file
Binary file not shown.
After Width: | Height: | Size: 1.7 KiB |
@ -287,15 +287,7 @@ body, html {
|
||||
z-index:999
|
||||
}
|
||||
|
||||
.filterSection{
|
||||
background: #FFF;
|
||||
padding: 15px 10px;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
border: 1px solid #333;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
|
||||
.filterSection .filterIcon{
|
||||
font-size: 16px;
|
||||
@ -310,6 +302,31 @@ body, html {
|
||||
width: 250px;
|
||||
}
|
||||
|
||||
.filterSection i{
|
||||
cursor: pointer;
|
||||
|
||||
/*map panel*/
|
||||
|
||||
.jstree-icon.folder{
|
||||
background: url(http://img.alicdn.com/bao/uploaded/TB1TqJjIpXXXXcYXFXXSutbFXXX.jpg_q90.jpg) no-repeat !important;
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
|
||||
.mapWrapper form{
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.mapWrapper ul{
|
||||
list-style: none;
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
.mapWrapper li{
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
||||
.mapWrapper .removeBtn{
|
||||
display: inline-block;
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
/*map panel end*/
|
||||
|
||||
|
@ -1,22 +1,23 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Anyproxy</title>
|
||||
<title>AnyProxy</title>
|
||||
<link rel="stylesheet" href="/css/uikit.gradient.min.css" />
|
||||
<link rel="stylesheet" href="/css/page.css" />
|
||||
<link rel="stylesheet" type="text/css" href="/css/jstree_style/style.min.css">
|
||||
|
||||
<link rel="icon" type="image/png" href="/favico.png" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="topHead">
|
||||
<div class="logoWrapper">
|
||||
<h1>Anyproxy</h1>
|
||||
<h1>AnyProxy</h1>
|
||||
<div id="J_indicatorEl"></div>
|
||||
</div>
|
||||
|
||||
<div class="ctrlWrapper">
|
||||
<a href="#"><span class="topBtn J_statusBtn"><i class="uk-icon-stop"></i>Stop</span></a>
|
||||
<a href="#"><span class="topBtn J_statusBtn btn_disable"><i class="uk-icon-play"></i>Resume</span></a>
|
||||
<a href="#"><span class="topBtn J_toggleFilterBtn"><i class="uk-icon-filter"></i>Filter</span></a>
|
||||
<a href="#"><span class="topBtn J_clearBtn"><i class="uk-icon-eraser"></i>Clear(Ctrl+X)</span></a>
|
||||
|
||||
<span class="sep">|</span>
|
||||
@ -24,21 +25,15 @@
|
||||
<a href="/qr_root" class="J_fetchRootQR" target="_blank"><span class="topBtn"><i class="uk-icon-qrcode"></i>QRCode of rootCA.crt</span></a>
|
||||
|
||||
<span class="sep">|</span>
|
||||
<a href="https://github.com/alibaba/anyproxy" target="_blank"><span class="topBtn"><i class="uk-icon-external-link-square"></i>Github</span></a>
|
||||
<a href="https://github.com/alibaba/anyproxy" target="_blank"><span class="topBtn"><i class="uk-icon-github"></i>Github</span></a>
|
||||
</div>
|
||||
|
||||
<div class="ruleDesc">
|
||||
<a href="#"><span class="topBtn J_showFilter"><i class="uk-icon-filter"></i>Filter</span></a>
|
||||
<a href="#"><span class="topBtn J_showMapPanel"><i class="uk-icon-level-down"></i>Map Local</span></a>
|
||||
<span><i class="uk-icon-chain"></i>Rule : {{rule}}</span>
|
||||
</div>
|
||||
|
||||
<div class="filterSection J_filterSection" style="display:none">
|
||||
<form class="uk-form">
|
||||
<input class="uk-form-large" type="text" id="J_filterKeyword" placeholder="type keywords or /^regExp$/" width="200"/>
|
||||
</form>
|
||||
<i class="uk-icon-times J_filterCloseBtn"></i>
|
||||
</div>
|
||||
|
||||
|
||||
<div style="clear:both"></div>
|
||||
</div>
|
||||
|
||||
|
4
web/lib/jquery.js
vendored
Normal file
4
web/lib/jquery.js
vendored
Normal file
File diff suppressed because one or more lines are too long
7420
web/lib/jstree.js
Executable file
7420
web/lib/jstree.js
Executable file
File diff suppressed because it is too large
Load Diff
19596
web/lib/react.js
vendored
19596
web/lib/react.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
27795
web/page.js
27795
web/page.js
File diff suppressed because one or more lines are too long
@ -1,88 +1,25 @@
|
||||
function init(React){
|
||||
|
||||
function dragableBar(initX,cb){
|
||||
var self = this,
|
||||
dragging = true;
|
||||
|
||||
var ghostbar = $('<div class="ghostbar"></div>').css("left",initX).prependTo('body');
|
||||
|
||||
$(document).mousemove(function(e){
|
||||
e.preventDefault();
|
||||
ghostbar.css("left",e.pageX + "px");
|
||||
});
|
||||
|
||||
$(document).mouseup(function(e){
|
||||
if(!dragging) return;
|
||||
|
||||
dragging = false;
|
||||
|
||||
var deltaPageX = e.pageX - initX;
|
||||
cb && cb.call(null,{
|
||||
delta : deltaPageX,
|
||||
finalX : e.pageX
|
||||
});
|
||||
|
||||
ghostbar.remove();
|
||||
$(document).unbind('mousemove');
|
||||
});
|
||||
}
|
||||
|
||||
var DetailPanel = React.createClass({
|
||||
getInitialState : function(){
|
||||
return {
|
||||
show : false,
|
||||
data : {},
|
||||
body : {id : -1, content : null},
|
||||
left : "35%"
|
||||
};
|
||||
},
|
||||
componentDidMount:function(){
|
||||
var self = this;
|
||||
$(document).on("keyup",function(e){
|
||||
if(e.keyCode == 27){ //ESC
|
||||
self.setState({
|
||||
show : false
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
setHide:function(){
|
||||
this.setState({
|
||||
show : false
|
||||
});
|
||||
},
|
||||
setShow:function(ifShow){
|
||||
this.setState({
|
||||
show : true
|
||||
});
|
||||
},
|
||||
loadBody:function(){
|
||||
var self = this,
|
||||
id = self.state.data.id;
|
||||
id = self.props.data.id;
|
||||
if(!id) return;
|
||||
|
||||
ws.reqBody(id,function(content){
|
||||
if(content.id == self.state.data.id){
|
||||
if(content.id == self.props.data.id){
|
||||
self.setState({
|
||||
body : content
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
dealDrag:function(){
|
||||
var self = this,
|
||||
leftVal = $(React.findDOMNode(this.refs.mainOverlay)).css("left");
|
||||
dragableBar(leftVal, function(data){
|
||||
if(data && data.finalX){
|
||||
if(window.innerWidth - data.finalX < 200){
|
||||
data.finalX = window.innerWidth - 200;
|
||||
}
|
||||
self.setState({
|
||||
left : data.finalX + "px"
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
render : function(){
|
||||
var reqHeaderSection = [],
|
||||
resHeaderSection = [],
|
||||
@ -90,9 +27,9 @@ function init(React){
|
||||
detailSection,
|
||||
bodyContent;
|
||||
|
||||
if(this.state.data.reqHeader){
|
||||
for(var key in this.state.data.reqHeader){
|
||||
reqHeaderSection.push(<li key={"reqHeader_" + key}><strong>{key}</strong> : {this.state.data.reqHeader[key]}</li>)
|
||||
if(this.props.data.reqHeader){
|
||||
for(var key in this.props.data.reqHeader){
|
||||
reqHeaderSection.push(<li key={"reqHeader_" + key}><strong>{key}</strong> : {this.props.data.reqHeader[key]}</li>)
|
||||
}
|
||||
}
|
||||
|
||||
@ -102,7 +39,7 @@ function init(React){
|
||||
<h4 className="subTitle">request</h4>
|
||||
<div className="detail">
|
||||
<ul className="uk-list">
|
||||
<li>{this.state.data.method} <span title="{this.state.data.path}">{this.state.data.path}</span> HTTP/1.1</li>
|
||||
<li>{this.props.data.method} <span title="{this.props.data.path}">{this.props.data.path}</span> HTTP/1.1</li>
|
||||
{reqHeaderSection}
|
||||
</ul>
|
||||
</div>
|
||||
@ -111,24 +48,24 @@ function init(React){
|
||||
<section className="reqBody">
|
||||
<h4 className="subTitle">request body</h4>
|
||||
<div className="detail">
|
||||
<p>{this.state.data.reqBody}</p>
|
||||
<p>{this.props.data.reqBody}</p>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
);
|
||||
|
||||
if(this.state.data.statusCode){
|
||||
if(this.props.data.statusCode){
|
||||
|
||||
if(this.state.body.id == this.state.data.id){
|
||||
if(this.state.body.id == this.props.data.id){
|
||||
bodyContent = (<pre className="resBodyContent">{this.state.body.body}</pre>);
|
||||
}else{
|
||||
bodyContent = null;
|
||||
this.loadBody();
|
||||
}
|
||||
|
||||
if(this.state.data.resHeader){
|
||||
for(var key in this.state.data.resHeader){
|
||||
resHeaderSection.push(<li key={"resHeader_" + key}><strong>{key}</strong> : {this.state.data.resHeader[key]}</li>)
|
||||
if(this.props.data.resHeader){
|
||||
for(var key in this.props.data.resHeader){
|
||||
resHeaderSection.push(<li key={"resHeader_" + key}><strong>{key}</strong> : {this.props.data.resHeader[key]}</li>)
|
||||
}
|
||||
}
|
||||
|
||||
@ -138,7 +75,7 @@ function init(React){
|
||||
<h4 className="subTitle">response header</h4>
|
||||
<div className="detail">
|
||||
<ul className="uk-list">
|
||||
<li>HTTP/1.1 <span className={"http_status http_status_" + this.state.data.statusCode}>{this.state.data.statusCode}</span></li>
|
||||
<li>HTTP/1.1 <span className={"http_status http_status_" + this.props.data.statusCode}>{this.props.data.statusCode}</span></li>
|
||||
{resHeaderSection}
|
||||
</ul>
|
||||
</div>
|
||||
@ -153,17 +90,10 @@ function init(React){
|
||||
}
|
||||
|
||||
return (
|
||||
<div style={{display:this.state.show ? "block" :"none"}}>
|
||||
<div className="overlay_mask" onClick={this.setHide}></div>
|
||||
<div className="recordDetailOverlay" ref="mainOverlay" style={{left: this.state.left}}>
|
||||
<div className="dragbar" onMouseDown={this.dealDrag}></div>
|
||||
<span className="escBtn" onClick={this.setHide}>Close (ESC)</span>
|
||||
<div>
|
||||
{summarySection}
|
||||
{detailSection}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
39
web/src/filter.js
Normal file
39
web/src/filter.js
Normal file
@ -0,0 +1,39 @@
|
||||
function init(React){
|
||||
|
||||
var Filter = React.createClass({
|
||||
|
||||
dealChange:function(){
|
||||
var self = this,
|
||||
userInput = React.findDOMNode(self.refs.keywordInput).value;
|
||||
|
||||
self.props.onChangeKeyword && self.props.onChangeKeyword.call(null,userInput);
|
||||
},
|
||||
setFocus:function(){
|
||||
var self = this;
|
||||
React.findDOMNode(self.refs.keywordInput).focus();
|
||||
},
|
||||
componentDidUpdate:function(){
|
||||
this.setFocus();
|
||||
},
|
||||
render:function(){
|
||||
var self = this;
|
||||
|
||||
return (
|
||||
<div className="filterSection">
|
||||
<h4 className="subTitle">Log Filter</h4>
|
||||
|
||||
<form className="uk-form">
|
||||
<input className="uk-form-large" ref="keywordInput" onChange={self.dealChange} type="text" placeholder="type keywords or /^regExp$/" width="300"/>
|
||||
</form>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
componentDidMount:function(){
|
||||
this.setFocus();
|
||||
}
|
||||
});
|
||||
|
||||
return Filter;
|
||||
}
|
||||
|
||||
module.exports.init = init;
|
@ -1,10 +1,15 @@
|
||||
require("../lib/zepto");
|
||||
window.$ = window.jQuery = require("../lib/jquery");
|
||||
|
||||
var EventManager = require('../lib/event'),
|
||||
Anyproxy_wsUtil = require("../lib/anyproxy_wsUtil"),
|
||||
React = require("../lib/react");
|
||||
|
||||
var WsIndicator = require("./wsIndicator").init(React),
|
||||
RecordPanel = require("./recordPanel").init(React);
|
||||
RecordPanel = require("./recordPanel").init(React),
|
||||
MapPanel = require("./mapPanel").init(React),
|
||||
Detail = require("./detailPanel").init(React),
|
||||
Popup = require("./popup").init(React),
|
||||
Filter = require("./filter").init(React);
|
||||
|
||||
var ifPause = false,
|
||||
recordSet = [];
|
||||
@ -15,6 +20,7 @@ var ifPause = false,
|
||||
//Event : wsEnd
|
||||
var eventCenter = new EventManager();
|
||||
|
||||
|
||||
//invoke AnyProxy web socket util
|
||||
(function(){
|
||||
try{
|
||||
@ -63,7 +69,19 @@ var eventCenter = new EventManager();
|
||||
})();
|
||||
|
||||
|
||||
//record panel
|
||||
//init popup
|
||||
var pop;
|
||||
(function(){
|
||||
$("body").append('<div id="J_popOuter"></div>');
|
||||
pop = React.render(
|
||||
<Popup />,
|
||||
document.getElementById("J_popOuter")
|
||||
);
|
||||
})();
|
||||
|
||||
|
||||
//init record panel
|
||||
var recorder;
|
||||
(function(){
|
||||
//merge : right --> left
|
||||
function util_merge(left,right){
|
||||
@ -89,29 +107,40 @@ var eventCenter = new EventManager();
|
||||
// React.addons.Perf.stop();
|
||||
}
|
||||
}
|
||||
|
||||
function showDetail(data){
|
||||
pop.setState({
|
||||
show: true,
|
||||
content : <Detail data={data}/>,
|
||||
left:"35%"
|
||||
});
|
||||
}
|
||||
|
||||
eventCenter.addListener("wsGetUpdate",updateRecordSet);
|
||||
|
||||
var Panel = React.render(
|
||||
<RecordPanel />,
|
||||
document.getElementById("J_content")
|
||||
);
|
||||
|
||||
eventCenter.addListener('recordSetUpdated',function(){
|
||||
Panel.setState({
|
||||
recorder.setState({
|
||||
list : recordSet
|
||||
});
|
||||
});
|
||||
|
||||
eventCenter.addListener("filterUpdated",function(newKeyword){
|
||||
Panel.setState({
|
||||
recorder.setState({
|
||||
filter: newKeyword
|
||||
});
|
||||
});
|
||||
|
||||
//init recorder panel
|
||||
recorder = React.render(
|
||||
<RecordPanel onSelect={showDetail}/>,
|
||||
document.getElementById("J_content")
|
||||
);
|
||||
})();
|
||||
|
||||
|
||||
//action bar
|
||||
(function(){
|
||||
//clear log
|
||||
function clearLogs(){
|
||||
recordSet = [];
|
||||
eventCenter.dispatchEvent("recordSetUpdated");
|
||||
@ -130,6 +159,7 @@ var eventCenter = new EventManager();
|
||||
clearLogs();
|
||||
});
|
||||
|
||||
//start , pause
|
||||
var statusBtn = $(".J_statusBtn");
|
||||
statusBtn.on("click",function(e){
|
||||
e.stopPropagation();
|
||||
@ -145,26 +175,41 @@ var eventCenter = new EventManager();
|
||||
}
|
||||
});
|
||||
|
||||
function switchFilterWidget(ifToShow){
|
||||
if(ifToShow){
|
||||
$(".J_filterSection").show();
|
||||
$("#J_filterKeyword").focus();
|
||||
}else{
|
||||
$(".J_filterSection").hide();
|
||||
$("#J_filterKeyword").val("");
|
||||
}
|
||||
//filter
|
||||
(function (){
|
||||
function updateKeyword(key){
|
||||
eventCenter.dispatchEvent("filterUpdated",key);
|
||||
}
|
||||
|
||||
$(".J_toggleFilterBtn").on("click",function(){
|
||||
switchFilterWidget( $(".J_filterSection").css("display") == "none" );
|
||||
var filter = (<Filter onChangeKeyword={updateKeyword} />);
|
||||
function showFilter(){
|
||||
pop.setState({
|
||||
show : true,
|
||||
content : filter,
|
||||
left:"70%"
|
||||
});
|
||||
}
|
||||
|
||||
$(".J_filterCloseBtn").on("click",function(){
|
||||
switchFilterWidget(false);
|
||||
});
|
||||
|
||||
|
||||
$("#J_filterKeyword").on("change keyup",function(){
|
||||
eventCenter.dispatchEvent("filterUpdated",this.value);
|
||||
$(".J_showFilter").on("click",function(){
|
||||
showFilter();
|
||||
});
|
||||
})();
|
||||
|
||||
//map local
|
||||
(function(){
|
||||
var mapPanel = (<MapPanel />);
|
||||
function showMap(){
|
||||
pop.setState({
|
||||
show : true,
|
||||
content : mapPanel,
|
||||
left:"70%"
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
$(".J_showMapPanel").on("click",function(){
|
||||
showMap();
|
||||
});
|
||||
})();
|
||||
|
||||
})();
|
114
web/src/mapForm.js
Normal file
114
web/src/mapForm.js
Normal file
@ -0,0 +1,114 @@
|
||||
require("../lib/jstree");
|
||||
|
||||
function init(React){
|
||||
function fetchTree(root,cb){
|
||||
if(!root || root == "#"){
|
||||
root = "";
|
||||
}
|
||||
|
||||
$.getJSON("/filetree?root=" + root,function(resObj){
|
||||
var ret = [];
|
||||
try{
|
||||
$.each(resObj.directory, function(k,item){
|
||||
if(item.name.indexOf(".") == 0) return;
|
||||
ret.push({
|
||||
text : item.name,
|
||||
id : item.fullPath,
|
||||
icon : "uk-icon-folder",
|
||||
children : true
|
||||
});
|
||||
});
|
||||
|
||||
$.each(resObj.file, function(k,item){
|
||||
if(item.name.indexOf(".") == 0) return;
|
||||
ret.push({
|
||||
text : item.name,
|
||||
id : item.fullPath,
|
||||
icon : 'uk-icon-file-o',
|
||||
children : false
|
||||
});
|
||||
});
|
||||
}catch(e){}
|
||||
cb && cb.call(null,ret);
|
||||
});
|
||||
}
|
||||
|
||||
var MapForm = React.createClass({
|
||||
|
||||
submitData:function(){
|
||||
var self = this,
|
||||
result = {};
|
||||
|
||||
var filePath = React.findDOMNode(self.refs.localFilePath).value,
|
||||
keyword = React.findDOMNode(self.refs.keywordInput).value;
|
||||
|
||||
if(filePath && keyword){
|
||||
self.props.onSubmit.call(null,{
|
||||
keyword : keyword,
|
||||
local : filePath
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
render:function(){
|
||||
var self = this;
|
||||
return (
|
||||
<div>
|
||||
<form className="uk-form uk-form-stacked">
|
||||
<fieldset>
|
||||
<legend>add rule</legend>
|
||||
|
||||
<div className="uk-form-row">
|
||||
<label className="uk-form-label" htmlFor="map_keywordInput">keyword</label>
|
||||
<div className="uk-form-controls">
|
||||
<input type="text" id="map_keywordInput" ref="keywordInput" placeholder="keyword" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="uk-form-row">
|
||||
<label className="uk-form-label" htmlFor="map_localFilePath">local file</label>
|
||||
<div className="uk-form-controls">
|
||||
<input type="text" id="map_localFilePath" ref="localFilePath" placeholder="keyword" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</fieldset>
|
||||
</form>
|
||||
|
||||
<div ref="treeWrapper"></div>
|
||||
<button className="uk-button" onClick={self.submitData}>Add</button>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
||||
componentDidMount :function(){
|
||||
var self = this;
|
||||
var wrapperEl = $(React.findDOMNode(self.refs.treeWrapper)),
|
||||
filePathInput = React.findDOMNode(self.refs.localFilePath);
|
||||
|
||||
wrapperEl.jstree({
|
||||
'core' : {
|
||||
'data' : function (node, cb) {
|
||||
fetchTree(node.id,cb);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
wrapperEl.on("changed.jstree", function (e, data) {
|
||||
if(data && data.selected && data.selected.length){
|
||||
//is folder
|
||||
if(/folder/.test(data.node.icon)) return;
|
||||
|
||||
var item = data.selected[0];
|
||||
filePathInput.value = item;
|
||||
}
|
||||
});
|
||||
|
||||
},
|
||||
componentDidUpdate:function(){}
|
||||
});
|
||||
|
||||
return MapForm;
|
||||
}
|
||||
|
||||
module.exports.init = init;
|
80
web/src/mapList.js
Normal file
80
web/src/mapList.js
Normal file
@ -0,0 +1,80 @@
|
||||
function init(React){
|
||||
var MapList = React.createClass({
|
||||
getInitialState:function(){
|
||||
return {
|
||||
ruleList : []
|
||||
}
|
||||
},
|
||||
appendRecord:function(data){
|
||||
var self = this,
|
||||
newState = self.state.ruleList;
|
||||
|
||||
if(data && data.keyword && data.local){
|
||||
newState.push({
|
||||
keyword : data.keyword,
|
||||
local : data.local
|
||||
});
|
||||
|
||||
self.setState({
|
||||
ruleList: newState
|
||||
});
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
removeRecord:function(index){
|
||||
var self = this,
|
||||
newList = self.state.ruleList;
|
||||
|
||||
newList.splice(index,1);
|
||||
self.setState({
|
||||
ruleList : newList
|
||||
});
|
||||
},
|
||||
render:function(){
|
||||
var self = this,
|
||||
collection = [];
|
||||
|
||||
collection = self.state.ruleList.map(function(item,index){
|
||||
return (
|
||||
<li>
|
||||
<strong>{item.keyword}</strong><a className="removeBtn" href="#" onClick={self.removeRecord.bind(self,index)}>remove</a><br />
|
||||
<span>{item.local}</span>
|
||||
</li>
|
||||
);
|
||||
});
|
||||
|
||||
return (
|
||||
<ul className="mapRuleList">
|
||||
{collection}
|
||||
</ul>
|
||||
);
|
||||
},
|
||||
componentDidMount :function(){
|
||||
var self = this;
|
||||
$.getJSON("/getMapConfig",function(data){
|
||||
self.setState({
|
||||
ruleList : data
|
||||
});
|
||||
});
|
||||
},
|
||||
componentDidUpdate:function(){
|
||||
var self = this;
|
||||
//sync config
|
||||
|
||||
var currentList = self.state.ruleList;
|
||||
$.ajax({
|
||||
method : "POST",
|
||||
url : "/setMapConfig",
|
||||
contentType :"application/json",
|
||||
data : JSON.stringify(currentList),
|
||||
dataType : "json",
|
||||
success :function(res){}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return MapList;
|
||||
}
|
||||
|
||||
module.exports.init = init;
|
32
web/src/mapPanel.js
Normal file
32
web/src/mapPanel.js
Normal file
@ -0,0 +1,32 @@
|
||||
require("../lib/jstree");
|
||||
|
||||
function init(React){
|
||||
var MapForm = require("./mapForm").init(React),
|
||||
MapList = require("./mapList").init(React);
|
||||
|
||||
var MapPanel = React.createClass({
|
||||
appendRecord : function(data){
|
||||
var self = this,
|
||||
listComponent = self.refs.list;
|
||||
|
||||
listComponent.appendRecord(data);
|
||||
},
|
||||
|
||||
render:function(){
|
||||
var self = this;
|
||||
return (
|
||||
<div className="mapWrapper">
|
||||
<h4 className="subTitle">Current Config</h4>
|
||||
<MapList ref="list"/>
|
||||
|
||||
<h4 className="subTitle">Map Local</h4>
|
||||
<MapForm onSubmit={self.appendRecord}/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
return MapPanel;
|
||||
}
|
||||
|
||||
module.exports.init = init;
|
94
web/src/popup.js
Normal file
94
web/src/popup.js
Normal file
@ -0,0 +1,94 @@
|
||||
function init(React){
|
||||
|
||||
function dragableBar(initX,cb){
|
||||
var self = this,
|
||||
dragging = true;
|
||||
|
||||
var ghostbar = $('<div class="ghostbar"></div>').css("left",initX).prependTo('body');
|
||||
|
||||
$(document).mousemove(function(e){
|
||||
e.preventDefault();
|
||||
ghostbar.css("left",e.pageX + "px");
|
||||
});
|
||||
|
||||
$(document).mouseup(function(e){
|
||||
if(!dragging) return;
|
||||
|
||||
dragging = false;
|
||||
|
||||
var deltaPageX = e.pageX - initX;
|
||||
cb && cb.call(null,{
|
||||
delta : deltaPageX,
|
||||
finalX : e.pageX
|
||||
});
|
||||
|
||||
ghostbar.remove();
|
||||
$(document).unbind('mousemove');
|
||||
});
|
||||
}
|
||||
|
||||
var Popup = React.createClass({
|
||||
getInitialState : function(){
|
||||
return {
|
||||
show : false,
|
||||
left : "35%",
|
||||
content : null
|
||||
};
|
||||
},
|
||||
componentDidMount:function(){
|
||||
var self = this;
|
||||
$(document).on("keyup",function(e){
|
||||
if(e.keyCode == 27){ //ESC
|
||||
self.setState({
|
||||
show : false
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
setHide:function(){
|
||||
this.setState({
|
||||
show : false
|
||||
});
|
||||
},
|
||||
setShow:function(ifShow){
|
||||
this.setState({
|
||||
show : true
|
||||
});
|
||||
},
|
||||
dealDrag:function(){
|
||||
var self = this,
|
||||
leftVal = $(React.findDOMNode(this.refs.mainOverlay)).css("left");
|
||||
dragableBar(leftVal, function(data){
|
||||
if(data && data.finalX){
|
||||
if(window.innerWidth - data.finalX < 200){
|
||||
data.finalX = window.innerWidth - 200;
|
||||
}
|
||||
self.setState({
|
||||
left : data.finalX + "px"
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
componentDidUpdate:function(){
|
||||
|
||||
},
|
||||
render : function(){
|
||||
return (
|
||||
<div style={{display:this.state.show ? "block" :"none"}}>
|
||||
<div className="overlay_mask" onClick={this.setHide}></div>
|
||||
<div className="recordDetailOverlay" ref="mainOverlay" style={{left: this.state.left}}>
|
||||
<div className="dragbar" onMouseDown={this.dealDrag}></div>
|
||||
<span className="escBtn" onClick={this.setHide}>Close (ESC)</span>
|
||||
<div>
|
||||
{this.state.content}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
return Popup;
|
||||
}
|
||||
|
||||
module.exports.init = init;
|
@ -9,8 +9,9 @@ function init(React){
|
||||
};
|
||||
},
|
||||
render : function(){
|
||||
var rowCollection = [],
|
||||
filterStr = this.state.filter,
|
||||
var self = this,
|
||||
rowCollection = [],
|
||||
filterStr = self.state.filter,
|
||||
filter = filterStr;
|
||||
|
||||
//regexp
|
||||
@ -20,8 +21,8 @@ function init(React){
|
||||
}catch(e){}
|
||||
}
|
||||
|
||||
for(var i = this.state.list.length-1 ; i >=0 ; i--){
|
||||
var item = this.state.list[i];
|
||||
for(var i = self.state.list.length-1 ; i >=0 ; i--){
|
||||
var item = self.state.list[i];
|
||||
if(item){
|
||||
if(filter && item){
|
||||
try{
|
||||
@ -40,7 +41,7 @@ function init(React){
|
||||
item._needRender = false;
|
||||
}
|
||||
|
||||
rowCollection.push(<RecordRow key={item.id} data={item}></RecordRow>);
|
||||
rowCollection.push(<RecordRow key={item.id} data={item} onSelect={self.props.onSelect.bind(self,item)}></RecordRow>);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,12 +1,4 @@
|
||||
function init(React){
|
||||
var DetailPanel = require("./detailPanel").init(React);
|
||||
|
||||
$("body").append('<div id="J_detailPanel"></div>');
|
||||
var detail = React.render(
|
||||
<DetailPanel />,
|
||||
document.getElementById("J_detailPanel")
|
||||
);
|
||||
|
||||
function dateFormat(date,fmt) {
|
||||
var o = {
|
||||
"M+": date.getMonth() + 1, //月份
|
||||
@ -26,12 +18,6 @@ function init(React){
|
||||
getInitialState : function(){
|
||||
return null;
|
||||
},
|
||||
handleClick:function(e){
|
||||
detail.setState({
|
||||
data : this.props.data,
|
||||
show : true
|
||||
});
|
||||
},
|
||||
render : function(){
|
||||
var trClassesArr = [],
|
||||
trClasses;
|
||||
@ -45,7 +31,7 @@ function init(React){
|
||||
var dateStr = dateFormat(new Date(this.props.data.startTime),"hh:mm:ss");
|
||||
|
||||
return(
|
||||
<tr className={trClasses} onClick={this.handleClick}>
|
||||
<tr className={trClasses} onClick={this.props.onSelect}>
|
||||
<td className="data_id">{this.props.data._id}</td>
|
||||
<td>{this.props.data.method} <span className={"protocol protocol_" + this.props.data.protocol} title="https"><i className="uk-icon-lock"></i></span> </td>
|
||||
<td className={"http_status http_status_" + this.props.data.statusCode}>{this.props.data.statusCode}</td>
|
||||
@ -64,7 +50,6 @@ function init(React){
|
||||
});
|
||||
|
||||
return RecordRow;
|
||||
|
||||
}
|
||||
|
||||
module.exports.init = init;
|
Loading…
x
Reference in New Issue
Block a user