diff options
author | Maximilian Hils <git@maximilianhils.com> | 2016-06-10 12:03:56 -0700 |
---|---|---|
committer | Maximilian Hils <git@maximilianhils.com> | 2016-06-10 12:03:56 -0700 |
commit | 0b241a1da71ef9eb7632fc0e32abcf061dcbd217 (patch) | |
tree | 703f1a5ff9d9c00b4bc36c5e4ded4583af6b87c3 /web/src/js/components/FlowTable | |
parent | 11fb21719179f243b9f2a069cba42c1d7f3722c0 (diff) | |
parent | c33df55919cf2238deff34b22856f8304e6279e3 (diff) | |
download | mitmproxy-0b241a1da71ef9eb7632fc0e32abcf061dcbd217.tar.gz mitmproxy-0b241a1da71ef9eb7632fc0e32abcf061dcbd217.tar.bz2 mitmproxy-0b241a1da71ef9eb7632fc0e32abcf061dcbd217.zip |
Merge remote-tracking branch 'jason/master'
Diffstat (limited to 'web/src/js/components/FlowTable')
-rw-r--r-- | web/src/js/components/FlowTable/FlowColumns.jsx | 137 | ||||
-rw-r--r-- | web/src/js/components/FlowTable/FlowRow.jsx | 28 | ||||
-rw-r--r-- | web/src/js/components/FlowTable/FlowTableHead.jsx | 43 |
3 files changed, 208 insertions, 0 deletions
diff --git a/web/src/js/components/FlowTable/FlowColumns.jsx b/web/src/js/components/FlowTable/FlowColumns.jsx new file mode 100644 index 00000000..11c0796c --- /dev/null +++ b/web/src/js/components/FlowTable/FlowColumns.jsx @@ -0,0 +1,137 @@ +import React, { Component } from 'react' +import classnames from 'classnames' +import { RequestUtils, ResponseUtils } from '../../flow/utils.js' +import { formatSize, formatTimeDelta } from '../../utils.js' + +export function TLSColumn({ flow }) { + return ( + <td className={classnames('col-tls', flow.request.scheme === 'https' ? 'col-tls-https' : 'col-tls-http')}></td> + ) +} + +TLSColumn.sortKeyFun = flow => flow.request.scheme +TLSColumn.headerClass = 'col-tls' +TLSColumn.headerName = '' + +export function IconColumn({ flow }) { + return ( + <td className="col-icon"> + <div className={classnames('resource-icon', IconColumn.getIcon(flow))}></div> + </td> + ) +} + +IconColumn.headerClass = 'col-icon' +IconColumn.headerName = '' + +IconColumn.getIcon = flow => { + if (!flow.response) { + return 'resource-icon-plain' + } + + var contentType = ResponseUtils.getContentType(flow.response) || '' + + // @todo We should assign a type to the flow somewhere else. + if (flow.response.status_code === 304) { + return 'resource-icon-not-modified' + } + if (300 <= flow.response.status_code && flow.response.status_code < 400) { + return 'resource-icon-redirect' + } + if (contentType.indexOf('image') >= 0) { + return 'resource-icon-image' + } + if (contentType.indexOf('javascript') >= 0) { + return 'resource-icon-js' + } + if (contentType.indexOf('css') >= 0) { + return 'resource-icon-css' + } + if (contentType.indexOf('html') >= 0) { + return 'resource-icon-document' + } + + return 'resource-icon-plain' +} + +export function PathColumn({ flow }) { + return ( + <td className="col-path"> + {flow.request.is_replay && ( + <i className="fa fa-fw fa-repeat pull-right"></i> + )} + {flow.intercepted && ( + <i className="fa fa-fw fa-pause pull-right"></i> + )} + {RequestUtils.pretty_url(flow.request)} + </td> + ) +} + +PathColumn.sortKeyFun = flow => RequestUtils.pretty_url(flow.request) +PathColumn.headerClass = 'col-path' +PathColumn.headerName = 'Path' + +export function MethodColumn({ flow }) { + return ( + <td className="col-method">{flow.request.method}</td> + ) +} + +MethodColumn.sortKeyFun = flow => flow.request.method +MethodColumn.headerClass = 'col-method' +MethodColumn.headerName = 'Method' + +export function StatusColumn({ flow }) { + return ( + <td className="col-status">{flow.response && flow.response.status_code}</td> + ) +} + +StatusColumn.sortKeyFun = flow => flow.response && flow.response.status_code +StatusColumn.headerClass = 'col-status' +StatusColumn.headerName = 'Status' + +export function SizeColumn({ flow }) { + return ( + <td className="col-size">{formatSize(SizeColumn.getTotalSize(flow))}</td> + ) +} + +SizeColumn.sortKeyFun = flow => { + let total = flow.request.contentLength + if (flow.response) { + total += flow.response.contentLength || 0 + } + return total +} + +SizeColumn.getTotalSize = SizeColumn.sortKeyFun +SizeColumn.headerClass = 'col-size' +SizeColumn.headerName = 'Size' + +export function TimeColumn({ flow }) { + return ( + <td className="col-time"> + {flow.response ? ( + formatTimeDelta(1000 * (flow.response.timestamp_end - flow.request.timestamp_start)) + ) : ( + '...' + )} + </td> + ) +} + +TimeColumn.sortKeyFun = flow => flow.response && flow.response.timestamp_end - flow.request.timestamp_start +TimeColumn.headerClass = 'col-time' +TimeColumn.headerName = 'Time' + +export default [ + TLSColumn, + IconColumn, + PathColumn, + MethodColumn, + StatusColumn, + SizeColumn, + TimeColumn, +] diff --git a/web/src/js/components/FlowTable/FlowRow.jsx b/web/src/js/components/FlowTable/FlowRow.jsx new file mode 100644 index 00000000..749bc0ce --- /dev/null +++ b/web/src/js/components/FlowTable/FlowRow.jsx @@ -0,0 +1,28 @@ +import React, { PropTypes } from 'react' +import classnames from 'classnames' +import columns from './FlowColumns' + +FlowRow.propTypes = { + onSelect: PropTypes.func.isRequired, + flow: PropTypes.object.isRequired, + highlighted: PropTypes.bool, + selected: PropTypes.bool, +} + +export default function FlowRow({ flow, selected, highlighted, onSelect }) { + const className = classnames({ + 'selected': selected, + 'highlighted': highlighted, + 'intercepted': flow.intercepted, + 'has-request': flow.request, + 'has-response': flow.response, + }) + + return ( + <tr className={className} onClick={() => onSelect(flow)}> + {columns.map(Column => ( + <Column key={Column.name} flow={flow}/> + ))} + </tr> + ) +} diff --git a/web/src/js/components/FlowTable/FlowTableHead.jsx b/web/src/js/components/FlowTable/FlowTableHead.jsx new file mode 100644 index 00000000..a46219d1 --- /dev/null +++ b/web/src/js/components/FlowTable/FlowTableHead.jsx @@ -0,0 +1,43 @@ +import React, { PropTypes } from 'react' +import { bindActionCreators } from 'redux' +import { connect } from 'react-redux' +import classnames from 'classnames' +import columns from './FlowColumns' + +import { setSort } from "../../ducks/flows" + +FlowTableHead.propTypes = { + onSort: PropTypes.func.isRequired, + sortDesc: React.PropTypes.bool.isRequired, + sortColumn: React.PropTypes.string, +} + +function FlowTableHead({ sortColumn, sortDesc, onSort }) { + const sortType = sortDesc ? 'sort-desc' : 'sort-asc' + + return ( + <tr> + {columns.map(Column => ( + <th className={classnames(Column.headerClass, sortColumn === Column.name && sortType)} + key={Column.name} + onClick={() => onClick(Column)}> + {Column.headerName} + </th> + ))} + </tr> + ) + + function onClick(Column) { + onSort({ sortColumn: Column.name, sortDesc: Column.name !== sortColumn ? false : !sortDesc }) + } +} + +export default connect( + state => ({ + sortDesc: state.flows.sort.sortDesc, + sortColumn: state.flows.sort.sortColumn, + }), + dispatch => bindActionCreators({ + onSort: setSort, + }, dispatch) +)(FlowTableHead) |