aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libmproxy/main.py1
-rw-r--r--libmproxy/web/__init__.py2
-rw-r--r--libmproxy/web/static/css/app.css13
-rw-r--r--libmproxy/web/static/js/app.js77
-rw-r--r--web/gulpfile.js1
-rw-r--r--web/src/css/eventlog.less22
-rw-r--r--web/src/js/actions.js6
-rw-r--r--web/src/js/components/eventlog.jsx15
-rw-r--r--web/src/js/components/proxyapp.jsx2
-rw-r--r--web/src/js/connection.js9
-rw-r--r--web/src/js/dispatcher.js8
-rw-r--r--web/src/js/stores/base.js3
-rw-r--r--web/src/js/stores/eventlogstore.js16
-rw-r--r--web/src/js/stores/settingstore.js4
-rw-r--r--web/src/js/utils.js13
15 files changed, 89 insertions, 103 deletions
diff --git a/libmproxy/main.py b/libmproxy/main.py
index a3c91c02..2d6a0119 100644
--- a/libmproxy/main.py
+++ b/libmproxy/main.py
@@ -220,7 +220,6 @@ def mitmweb(): # pragma: nocover
from . import web
check_versions()
- assert_utf8_env()
web_options, proxy_config = mitmweb_cmdline()
server = get_server(web_options.no_server, proxy_config)
diff --git a/libmproxy/web/__init__.py b/libmproxy/web/__init__.py
index 50b41b80..83a7bde4 100644
--- a/libmproxy/web/__init__.py
+++ b/libmproxy/web/__init__.py
@@ -101,7 +101,7 @@ class WebMaster(flow.FlowMaster):
def handle_log(self, l):
app.ClientConnection.broadcast(
- "event", {
+ "add_event", {
"message": l.msg,
"level": l.level
}
diff --git a/libmproxy/web/static/css/app.css b/libmproxy/web/static/css/app.css
index e5b9d134..6dd17c7d 100644
--- a/libmproxy/web/static/css/app.css
+++ b/libmproxy/web/static/css/app.css
@@ -69,22 +69,11 @@ header .menu {
}
.eventlog {
flex: 0 0 auto;
-}
-.eventlog pre {
margin: 0;
border-radius: 0;
height: 200px;
overflow: auto;
-}
-.eventlog .close-button {
- float: right;
- margin: -9px;
- padding: 4px;
- cursor: pointer;
- color: grey;
-}
-.eventlog .close-button:hover {
- color: black;
+ overflow-y: scroll;
}
footer {
box-shadow: 0 -1px 3px #d3d3d3;
diff --git a/libmproxy/web/static/js/app.js b/libmproxy/web/static/js/app.js
index 84eece87..5bc8de0d 100644
--- a/libmproxy/web/static/js/app.js
+++ b/libmproxy/web/static/js/app.js
@@ -1,6 +1,20 @@
+// http://blog.vjeux.com/2013/javascript/scroll-position-with-react.html (also contains inverse example)
+var AutoScrollMixin = {
+ componentWillUpdate: function () {
+ var node = this.getDOMNode();
+ this._shouldScrollBottom = node.scrollTop + node.clientHeight === node.scrollHeight;
+ },
+ componentDidUpdate: function () {
+ if (this._shouldScrollBottom) {
+ var node = this.getDOMNode();
+ node.scrollTop = node.scrollHeight;
+ }
+ },
+};
+
const PayloadSources = {
- VIEW_ACTION: "VIEW_ACTION",
- SERVER_ACTION: "SERVER_ACTION"
+ VIEW: "view",
+ SERVER: "server"
};
@@ -26,17 +40,17 @@ Dispatcher.prototype.dispatch = function (payload) {
AppDispatcher = new Dispatcher();
AppDispatcher.dispatchViewAction = function (action) {
- action.actionSource = PayloadSources.VIEW_ACTION;
+ action.source = PayloadSources.VIEW;
this.dispatch(action);
};
AppDispatcher.dispatchServerAction = function (action) {
- action.actionSource = PayloadSources.SERVER_ACTION;
+ action.source = PayloadSources.SERVER;
this.dispatch(action);
};
var ActionTypes = {
- SETTINGS_UPDATE: "SETTINGS_UPDATE",
- EVENTLOG_ADD: "EVENTLOG_ADD"
+ UPDATE_SETTINGS: "update_settings",
+ ADD_EVENT: "add_event"
};
var SettingsActions = {
@@ -46,7 +60,7 @@ var SettingsActions = {
//Facebook Flux: We do an optimistic update on the client already.
AppDispatcher.dispatchViewAction({
- actionType: ActionTypes.SETTINGS_UPDATE,
+ type: ActionTypes.UPDATE_SETTINGS,
settings: settings
});
}
@@ -59,8 +73,9 @@ EventEmitter.prototype.emit = function (event) {
if (!(event in this.listeners)) {
return;
}
+ var args = Array.prototype.slice.call(arguments, 1);
this.listeners[event].forEach(function (listener) {
- listener.apply(this, arguments);
+ listener.apply(this, args);
}.bind(this));
};
EventEmitter.prototype.addListener = function (event, f) {
@@ -92,8 +107,8 @@ _.extend(_SettingsStore.prototype, EventEmitter.prototype, {
return this.settings;
},
handle: function (action) {
- switch (action.actionType) {
- case ActionTypes.SETTINGS_UPDATE:
+ switch (action.type) {
+ case ActionTypes.UPDATE_SETTINGS:
this.settings = action.settings;
this.emit("change");
break;
@@ -115,19 +130,19 @@ AppDispatcher.register(SettingsStore.handle.bind(SettingsStore));
// See also: components/EventLog.react.js
function EventLogView(store, live) {
EventEmitter.call(this);
- this.$EventLogView_store = store;
+ this._store = store;
this.live = live;
this.log = [];
this.add = this.add.bind(this);
if (live) {
- this.$EventLogView_store.addListener("new_entry", this.add);
+ this._store.addListener(ActionTypes.ADD_EVENT, this.add);
}
}
_.extend(EventLogView.prototype, EventEmitter.prototype, {
close: function () {
- this.$EventLogView_store.removeListener("new_entry", this.add);
+ this._store.removeListener(ActionTypes.ADD_EVENT, this.add);
},
getAll: function () {
return this.log;
@@ -154,7 +169,8 @@ function _EventLogStore() {
_.extend(_EventLogStore.prototype, EventEmitter.prototype, {
getView: function (since) {
var view = new EventLogView(this, !since);
-
+ return view;
+ /*
//TODO: Really do bulk retrieval of last messages.
window.setTimeout(function () {
view.add_bulk([
@@ -185,11 +201,12 @@ _.extend(_EventLogStore.prototype, EventEmitter.prototype, {
});
}, 1000);
return view;
+ */
},
handle: function (action) {
- switch (action.actionType) {
- case ActionTypes.EVENTLOG_ADD:
- this.emit("new_message", action.message);
+ switch (action.type) {
+ case ActionTypes.ADD_EVENT:
+ this.emit(ActionTypes.ADD_EVENT, action.data);
break;
default:
return;
@@ -222,14 +239,7 @@ _Connection.prototype.onopen = function (open) {
_Connection.prototype.onmessage = function (message) {
//AppDispatcher.dispatchServerAction(...);
var m = JSON.parse(message.data);
- switch (m.type){
- case "flow":
- console.log("flow", m.data);
- break;
- case "event":
- console.log("event", m.data.message)
- break;
- }
+ AppDispatcher.dispatchServerAction(m);
};
_Connection.prototype.onerror = function (error) {
console.log("onerror", this, arguments);
@@ -368,6 +378,7 @@ var TrafficTable = React.createClass({displayName: 'TrafficTable',
/** @jsx React.DOM */
var EventLog = React.createClass({displayName: 'EventLog',
+ mixins:[AutoScrollMixin],
getInitialState: function () {
return {
log: []
@@ -392,16 +403,10 @@ var EventLog = React.createClass({displayName: 'EventLog',
});
},
render: function () {
- //var messages = this.state.log.map(row => (<div key={row.id}>{row.message}</div>));
- var messages = [];
- return (
- React.DOM.div({className: "eventlog"},
- React.DOM.pre(null,
- React.DOM.i({className: "fa fa-close close-button", onClick: this.close}),
- messages
- )
- )
- );
+ var messages = this.state.log.map(function(row) {
+ return (React.DOM.div({key: row.id}, row.message));
+ });
+ return React.DOM.pre({className: "eventlog"}, messages);
}
});
@@ -447,7 +452,7 @@ var ProxyAppMain = React.createClass({displayName: 'ProxyAppMain',
React.DOM.div({id: "container"},
Header({settings: this.state.settings}),
React.DOM.div({id: "main"}, this.props.activeRouteHandler(null)),
- this.state.settings.showEventLog ? EventLog(null) : null,
+ this.state.settings.showEventLog ? EventLog(null) : null,
Footer({settings: this.state.settings})
)
);
diff --git a/web/gulpfile.js b/web/gulpfile.js
index 4130012f..be44081d 100644
--- a/web/gulpfile.js
+++ b/web/gulpfile.js
@@ -32,6 +32,7 @@ var path = {
'vendor/react-bootstrap/react-bootstrap.js'
],
app: [
+ 'js/utils.js',
'js/dispatcher.js',
'js/actions.js',
'js/stores/base.js',
diff --git a/web/src/css/eventlog.less b/web/src/css/eventlog.less
index 6b0c0e61..993304cf 100644
--- a/web/src/css/eventlog.less
+++ b/web/src/css/eventlog.less
@@ -2,21 +2,9 @@
flex: 0 0 auto;
- pre {
- margin: 0;
- border-radius: 0;
- height: 200px;
- overflow: auto;
- }
-
- .close-button {
- float: right;
- margin: -9px;
- padding: 4px;
- cursor: pointer;
- color: grey;
- &:hover {
- color: black;
- }
- }
+ margin: 0;
+ border-radius: 0;
+ height: 200px;
+ overflow: auto;
+ overflow-y: scroll;
} \ No newline at end of file
diff --git a/web/src/js/actions.js b/web/src/js/actions.js
index 35cb83da..e55a1d16 100644
--- a/web/src/js/actions.js
+++ b/web/src/js/actions.js
@@ -1,6 +1,6 @@
var ActionTypes = {
- SETTINGS_UPDATE: "SETTINGS_UPDATE",
- EVENTLOG_ADD: "EVENTLOG_ADD"
+ UPDATE_SETTINGS: "update_settings",
+ ADD_EVENT: "add_event"
};
var SettingsActions = {
@@ -10,7 +10,7 @@ var SettingsActions = {
//Facebook Flux: We do an optimistic update on the client already.
AppDispatcher.dispatchViewAction({
- actionType: ActionTypes.SETTINGS_UPDATE,
+ type: ActionTypes.UPDATE_SETTINGS,
settings: settings
});
}
diff --git a/web/src/js/components/eventlog.jsx b/web/src/js/components/eventlog.jsx
index 340de8bd..32fc01ee 100644
--- a/web/src/js/components/eventlog.jsx
+++ b/web/src/js/components/eventlog.jsx
@@ -1,6 +1,7 @@
/** @jsx React.DOM */
var EventLog = React.createClass({
+ mixins:[AutoScrollMixin],
getInitialState: function () {
return {
log: []
@@ -25,15 +26,9 @@ var EventLog = React.createClass({
});
},
render: function () {
- //var messages = this.state.log.map(row => (<div key={row.id}>{row.message}</div>));
- var messages = [];
- return (
- <div className="eventlog">
- <pre>
- <i className="fa fa-close close-button" onClick={this.close}></i>
- {messages}
- </pre>
- </div>
- );
+ var messages = this.state.log.map(function(row) {
+ return (<div key={row.id}>{row.message}</div>);
+ });
+ return <pre className="eventlog">{messages}</pre>;
}
});
diff --git a/web/src/js/components/proxyapp.jsx b/web/src/js/components/proxyapp.jsx
index fff1d8d0..2f1a9861 100644
--- a/web/src/js/components/proxyapp.jsx
+++ b/web/src/js/components/proxyapp.jsx
@@ -27,7 +27,7 @@ var ProxyAppMain = React.createClass({
<div id="container">
<Header settings={this.state.settings}/>
<div id="main"><this.props.activeRouteHandler/></div>
- {this.state.settings.showEventLog ? <EventLog/> : null}
+ {this.state.settings.showEventLog ? <EventLog/> : null}
<Footer settings={this.state.settings}/>
</div>
);
diff --git a/web/src/js/connection.js b/web/src/js/connection.js
index a4369b5a..5d464e52 100644
--- a/web/src/js/connection.js
+++ b/web/src/js/connection.js
@@ -19,14 +19,7 @@ _Connection.prototype.onopen = function (open) {
_Connection.prototype.onmessage = function (message) {
//AppDispatcher.dispatchServerAction(...);
var m = JSON.parse(message.data);
- switch (m.type){
- case "flow":
- console.log("flow", m.data);
- break;
- case "event":
- console.log("event", m.data.message)
- break;
- }
+ AppDispatcher.dispatchServerAction(m);
};
_Connection.prototype.onerror = function (error) {
console.log("onerror", this, arguments);
diff --git a/web/src/js/dispatcher.js b/web/src/js/dispatcher.js
index 028ac4dc..65c4a4a0 100644
--- a/web/src/js/dispatcher.js
+++ b/web/src/js/dispatcher.js
@@ -1,6 +1,6 @@
const PayloadSources = {
- VIEW_ACTION: "VIEW_ACTION",
- SERVER_ACTION: "SERVER_ACTION"
+ VIEW: "view",
+ SERVER: "server"
};
@@ -26,10 +26,10 @@ Dispatcher.prototype.dispatch = function (payload) {
AppDispatcher = new Dispatcher();
AppDispatcher.dispatchViewAction = function (action) {
- action.actionSource = PayloadSources.VIEW_ACTION;
+ action.source = PayloadSources.VIEW;
this.dispatch(action);
};
AppDispatcher.dispatchServerAction = function (action) {
- action.actionSource = PayloadSources.SERVER_ACTION;
+ action.source = PayloadSources.SERVER;
this.dispatch(action);
};
diff --git a/web/src/js/stores/base.js b/web/src/js/stores/base.js
index 9a2dbd64..952fa847 100644
--- a/web/src/js/stores/base.js
+++ b/web/src/js/stores/base.js
@@ -5,8 +5,9 @@ EventEmitter.prototype.emit = function (event) {
if (!(event in this.listeners)) {
return;
}
+ var args = Array.prototype.slice.call(arguments, 1);
this.listeners[event].forEach(function (listener) {
- listener.apply(this, arguments);
+ listener.apply(this, args);
}.bind(this));
};
EventEmitter.prototype.addListener = function (event, f) {
diff --git a/web/src/js/stores/eventlogstore.js b/web/src/js/stores/eventlogstore.js
index 54c45939..976f7524 100644
--- a/web/src/js/stores/eventlogstore.js
+++ b/web/src/js/stores/eventlogstore.js
@@ -7,19 +7,19 @@
// See also: components/EventLog.react.js
function EventLogView(store, live) {
EventEmitter.call(this);
- this.$EventLogView_store = store;
+ this._store = store;
this.live = live;
this.log = [];
this.add = this.add.bind(this);
if (live) {
- this.$EventLogView_store.addListener("new_entry", this.add);
+ this._store.addListener(ActionTypes.ADD_EVENT, this.add);
}
}
_.extend(EventLogView.prototype, EventEmitter.prototype, {
close: function () {
- this.$EventLogView_store.removeListener("new_entry", this.add);
+ this._store.removeListener(ActionTypes.ADD_EVENT, this.add);
},
getAll: function () {
return this.log;
@@ -46,7 +46,8 @@ function _EventLogStore() {
_.extend(_EventLogStore.prototype, EventEmitter.prototype, {
getView: function (since) {
var view = new EventLogView(this, !since);
-
+ return view;
+ /*
//TODO: Really do bulk retrieval of last messages.
window.setTimeout(function () {
view.add_bulk([
@@ -77,11 +78,12 @@ _.extend(_EventLogStore.prototype, EventEmitter.prototype, {
});
}, 1000);
return view;
+ */
},
handle: function (action) {
- switch (action.actionType) {
- case ActionTypes.EVENTLOG_ADD:
- this.emit("new_message", action.message);
+ switch (action.type) {
+ case ActionTypes.ADD_EVENT:
+ this.emit(ActionTypes.ADD_EVENT, action.data);
break;
default:
return;
diff --git a/web/src/js/stores/settingstore.js b/web/src/js/stores/settingstore.js
index 0ba7d800..7eef9b8f 100644
--- a/web/src/js/stores/settingstore.js
+++ b/web/src/js/stores/settingstore.js
@@ -13,8 +13,8 @@ _.extend(_SettingsStore.prototype, EventEmitter.prototype, {
return this.settings;
},
handle: function (action) {
- switch (action.actionType) {
- case ActionTypes.SETTINGS_UPDATE:
+ switch (action.type) {
+ case ActionTypes.UPDATE_SETTINGS:
this.settings = action.settings;
this.emit("change");
break;
diff --git a/web/src/js/utils.js b/web/src/js/utils.js
new file mode 100644
index 00000000..39ad92fb
--- /dev/null
+++ b/web/src/js/utils.js
@@ -0,0 +1,13 @@
+// http://blog.vjeux.com/2013/javascript/scroll-position-with-react.html (also contains inverse example)
+var AutoScrollMixin = {
+ componentWillUpdate: function () {
+ var node = this.getDOMNode();
+ this._shouldScrollBottom = node.scrollTop + node.clientHeight === node.scrollHeight;
+ },
+ componentDidUpdate: function () {
+ if (this._shouldScrollBottom) {
+ var node = this.getDOMNode();
+ node.scrollTop = node.scrollHeight;
+ }
+ },
+};