aboutsummaryrefslogtreecommitdiffstats
path: root/web/src/js/components/flowdetail.jsx.js
diff options
context:
space:
mode:
authorMaximilian Hils <git@maximilianhils.com>2014-09-19 17:56:54 +0200
committerMaximilian Hils <git@maximilianhils.com>2014-09-19 17:56:54 +0200
commit818c5918b648b29f3692bd2cc6ebcf326d4d2497 (patch)
tree50346a97f281fb4138766f4c6deca5f789995a66 /web/src/js/components/flowdetail.jsx.js
parentb5e727da8869baf9d24720debf8ff6c6c22c8500 (diff)
downloadmitmproxy-818c5918b648b29f3692bd2cc6ebcf326d4d2497.tar.gz
mitmproxy-818c5918b648b29f3692bd2cc6ebcf326d4d2497.tar.bz2
mitmproxy-818c5918b648b29f3692bd2cc6ebcf326d4d2497.zip
web: display flow connection info
Diffstat (limited to 'web/src/js/components/flowdetail.jsx.js')
-rw-r--r--web/src/js/components/flowdetail.jsx.js123
1 files changed, 117 insertions, 6 deletions
diff --git a/web/src/js/components/flowdetail.jsx.js b/web/src/js/components/flowdetail.jsx.js
index e5fe37a0..7c984193 100644
--- a/web/src/js/components/flowdetail.jsx.js
+++ b/web/src/js/components/flowdetail.jsx.js
@@ -3,7 +3,7 @@
var FlowDetailNav = React.createClass({
render: function(){
- var items = ["request", "response", "details"].map(function(e){
+ var items = this.props.tabs.map(function(e){
var str = e.charAt(0).toUpperCase() + e.slice(1);
var className = this.props.active === e ? "active" : "";
var onClick = function(){
@@ -28,11 +28,11 @@ var Headers = React.createClass({
var rows = this.props.message.headers.map(function(header){
return (
<tr>
- <td className="header-name">{header[0]}</td>
+ <td className="header-name">{header[0]+":"}</td>
<td className="header-value">{header[1]}</td>
</tr>
);
- })
+ });
return (
<table className="header-table">
<tbody>
@@ -41,7 +41,7 @@ var Headers = React.createClass({
</table>
);
}
-})
+});
var FlowDetailRequest = React.createClass({
render: function(){
@@ -99,9 +99,106 @@ var FlowDetailResponse = React.createClass({
}
});
+var TimeStamp = React.createClass({
+ render: function() {
+ var ts, delta;
+
+ if(!this.props.t && this.props.optional){
+ //should be return null, but that triggers a React bug.
+ return <tr></tr>;
+ } else if (!this.props.t){
+ ts = "active";
+ } else {
+ ts = (new Date(this.props.t * 1000)).toISOString();
+ ts = ts.replace("T", " ").replace("Z","");
+
+ if(this.props.deltaTo){
+ delta = Math.round((this.props.t-this.props.deltaTo)*1000) + "ms";
+ delta = <span className="text-muted">{"(" + delta + ")"}</span>;
+ } else {
+ delta = null;
+ }
+ }
+
+ return <tr><td>{this.props.title + ":"}</td><td>{ts} {delta}</td></tr>;
+ }
+});
+
+var ConnectionInfo = React.createClass({
+
+ render: function() {
+ var conn = this.props.conn;
+ var address = conn.address.address.join(":");
+
+ var sni = <tr key="sni"></tr>; //should be null, but that triggers a React bug.
+ if(conn.sni){
+ sni = <tr key="sni"><td><abbr title="TLS Server Name Indication">TLS SNI:</abbr></td><td>{conn.sni}</td></tr>;
+ }
+ return (
+ <table className="connection-table">
+ <tbody>
+ <tr key="address"><td>Address:</td><td>{address}</td></tr>
+ {sni}
+ <TimeStamp title="Start time"
+ key="start"
+ t={conn.timestamp_start} />
+ <TimeStamp title="TCP Setup"
+ key="tcpsetup"
+ t={conn.timestamp_tcp_setup}
+ deltaTo={conn.timestamp_start}
+ optional={true} />
+ <TimeStamp title="SSL handshake"
+ key="sslsetup"
+ t={conn.timestamp_ssl_setup}
+ deltaTo={conn.timestamp_start}
+ optional={true} />
+ <TimeStamp title="End time"
+ key="end"
+ t={conn.timestamp_end}
+ deltaTo={conn.timestamp_start} />
+ </tbody>
+ </table>
+ );
+ }
+});
+
+var CertificateInfo = React.createClass({
+ render: function(){
+ //TODO: We should fetch human-readable certificate representation
+ // from the server
+ var flow = this.props.flow;
+ var client_conn = flow.client_conn;
+ var server_conn = flow.server_conn;
+ return (
+ <div>
+ {client_conn.cert ? <h4>Client Certificate</h4> : null}
+ {client_conn.cert ? <pre>{client_conn.cert}</pre> : null}
+
+ {server_conn.cert ? <h4>Server Certificate</h4> : null}
+ {server_conn.cert ? <pre>{server_conn.cert}</pre> : null}
+ </div>
+ );
+ }
+});
+
var FlowDetailConnectionInfo = React.createClass({
render: function(){
- return <section>details</section>;
+ var flow = this.props.flow;
+ var client_conn = flow.client_conn;
+ var server_conn = flow.server_conn;
+ return (
+ <section>
+
+ <h4>Client Connection</h4>
+ <ConnectionInfo conn={client_conn}/>
+
+ <h4>Server Connection</h4>
+ <ConnectionInfo conn={server_conn}/>
+
+ <CertificateInfo flow={flow}/>
+
+ </section>
+ );
}
});
@@ -112,13 +209,27 @@ var tabs = {
};
var FlowDetail = React.createClass({
+ getDefaultProps: function(){
+ return {
+ tabs: ["request","response", "details"]
+ };
+ },
mixins: [StickyHeadMixin],
+ nextTab: function(i) {
+ var currentIndex = this.props.tabs.indexOf(this.props.active);
+ // JS modulo operator doesn't correct negative numbers, make sure that we are positive.
+ var nextIndex = (currentIndex + i + this.props.tabs.length) % this.props.tabs.length;
+ this.props.selectTab(this.props.tabs[nextIndex]);
+ },
render: function(){
var flow = JSON.stringify(this.props.flow, null, 2);
var Tab = tabs[this.props.active];
return (
<div className="flow-detail" onScroll={this.adjustHead}>
- <FlowDetailNav ref="head" active={this.props.active} selectTab={this.props.selectTab}/>
+ <FlowDetailNav ref="head"
+ tabs={this.props.tabs}
+ active={this.props.active}
+ selectTab={this.props.selectTab}/>
<Tab flow={this.props.flow}/>
</div>
);