Search full request details

Summary: Simple implementation of searching through request/response body on "network" tab

Reviewed By: passy

Differential Revision: D18268026

fbshipit-source-id: 39386d2d6ec50b47c3ca3dec976821282b51636f
This commit is contained in:
Anton Nikolaev
2019-11-01 06:53:42 -07:00
committed by Facebook Github Bot
parent 691a4ee135
commit faaf8c4f32
5 changed files with 55 additions and 6 deletions

View File

@@ -283,8 +283,11 @@ ${request.headers
)
.join('\n')}`;
if (request.data) {
copyText += `\n\n${decodeBody(request)}`;
const requestData = request.data ? decodeBody(request) : null;
const responseData = response && response.data ? decodeBody(response) : null;
if (requestData) {
copyText += `\n\n${requestData}`;
}
if (response) {
@@ -300,8 +303,8 @@ ${response.headers
.join('\n')}`;
}
if (response) {
copyText += `\n\n${decodeBody(response)}`;
if (responseData) {
copyText += `\n\n${responseData}`;
}
return {
@@ -346,6 +349,8 @@ ${response.headers
sortKey: request.timestamp,
copyText,
highlightOnHover: true,
requestBody: requestData,
responseBody: responseData,
};
}
@@ -471,6 +476,7 @@ class NetworkTable extends PureComponent<NetworkTableProps, NetworkTableState> {
highlightedRows={this.props.highlightedRows}
rowLineHeight={26}
allowRegexSearch={true}
allowBodySearch={true}
zebra={false}
actions={<Button onClick={this.props.clear}>Clear Table</Button>}
/>

View File

@@ -56,6 +56,7 @@ type Props = {
toggled?: boolean;
className?: string;
label?: string;
tooltip?: string;
};
/**
@@ -71,7 +72,7 @@ type Props = {
export default class ToggleButton extends React.Component<Props> {
render() {
return (
<Container onClick={this.props.onClick}>
<Container onClick={this.props.onClick} title={this.props.tooltip}>
<StyledButton
className={this.props.className}
toggled={this.props.toggled || false}

View File

@@ -93,7 +93,9 @@ export type SearchableProps = {
searchTerm: string;
filters: Array<Filter>;
allowRegexSearch?: boolean;
allowBodySearch?: boolean;
regexEnabled?: boolean;
bodySearchEnabled?: boolean;
};
type Props = {
@@ -104,6 +106,7 @@ type Props = {
onFilterChange: (filters: Array<Filter>) => void;
defaultFilters: Array<Filter>;
allowRegexSearch: boolean;
allowBodySearch: boolean;
};
type State = {
@@ -112,6 +115,7 @@ type State = {
searchTerm: string;
hasFocus: boolean;
regexEnabled: boolean;
bodySearchEnabled: boolean;
compiledRegex: RegExp | null | undefined;
};
@@ -137,6 +141,7 @@ const Searchable = (
searchTerm: '',
hasFocus: false,
regexEnabled: false,
bodySearchEnabled: false,
compiledRegex: null,
};
@@ -149,6 +154,7 @@ const Searchable = (
| {
filters: Array<Filter>;
regexEnabled?: boolean;
bodySearchEnabled?: boolean;
searchTerm?: string;
}
| undefined;
@@ -192,6 +198,8 @@ const Searchable = (
searchTerm: searchTerm,
filters: savedState.filters || this.state.filters,
regexEnabled: savedState.regexEnabled || this.state.regexEnabled,
bodySearchEnabled:
savedState.bodySearchEnabled || this.state.bodySearchEnabled,
compiledRegex: compileRegex(searchTerm),
});
}
@@ -202,6 +210,7 @@ const Searchable = (
this.getTableKey() &&
(prevState.searchTerm !== this.state.searchTerm ||
prevState.regexEnabled != this.state.regexEnabled ||
prevState.bodySearchEnabled != this.state.bodySearchEnabled ||
prevState.filters !== this.state.filters)
) {
window.localStorage.setItem(
@@ -210,6 +219,7 @@ const Searchable = (
searchTerm: this.state.searchTerm,
filters: this.state.filters,
regexEnabled: this.state.regexEnabled,
bodySearchEnabled: this.state.bodySearchEnabled,
}),
);
if (this.props.onFilterChange != null) {
@@ -406,6 +416,12 @@ const Searchable = (
});
};
onBodySearchToggled = () => {
this.setState({
bodySearchEnabled: !this.state.bodySearchEnabled,
});
};
hasFocus = (): boolean => {
return this.state.focusedToken !== -1 || this.state.hasFocus;
};
@@ -464,6 +480,16 @@ const Searchable = (
label={'Regex'}
/>
) : null}
{this.props.allowBodySearch ? (
<ToggleButton
toggled={this.state.bodySearchEnabled}
onClick={this.onBodySearchToggled}
label={'Body'}
tooltip={
'Search request and response bodies (warning: this can be quite slow)'
}
/>
) : null}
{(this.state.searchTerm || this.state.filters.length > 0) && (
<Clear onClick={this.clear}>&times;</Clear>
)}
@@ -475,6 +501,7 @@ const Searchable = (
addFilter={this.addFilter}
searchTerm={this.state.searchTerm}
regexEnabled={this.state.regexEnabled}
bodySearchEnabled={this.state.bodySearchEnabled}
filters={this.state.filters}
/>,
];

View File

@@ -60,6 +60,7 @@ function rowMatchesRegex(values: Array<string>, regex: string): boolean {
function rowMatchesSearchTerm(
searchTerm: string,
isRegex: boolean,
isBodySearchEnabled: boolean,
row: TableBodyRow,
): boolean {
if (searchTerm == null || searchTerm.length === 0) {
@@ -68,6 +69,14 @@ function rowMatchesSearchTerm(
const rowValues = Object.keys(row.columns).map(key =>
textContent(row.columns[key].value),
);
if (isBodySearchEnabled) {
if (row.requestBody) {
rowValues.push(row.requestBody);
}
if (row.responseBody) {
rowValues.push(row.responseBody);
}
}
if (isRegex) {
return rowMatchesRegex(rowValues, searchTerm);
}
@@ -80,9 +89,10 @@ const filterRowsFactory = (
filters: Array<Filter>,
searchTerm: string,
regexSearch: boolean,
bodySearch: boolean,
) => (row: TableBodyRow): boolean =>
rowMatchesFilters(filters, row) &&
rowMatchesSearchTerm(searchTerm, regexSearch, row);
rowMatchesSearchTerm(searchTerm, regexSearch, bodySearch, row);
class SearchableManagedTable extends PureComponent<Props, State> {
static defaultProps = {
@@ -94,6 +104,7 @@ class SearchableManagedTable extends PureComponent<Props, State> {
this.props.filters,
this.props.searchTerm,
this.props.regexEnabled || false,
this.props.bodySearchEnabled || false,
),
};
@@ -105,6 +116,7 @@ class SearchableManagedTable extends PureComponent<Props, State> {
if (
nextProps.searchTerm !== this.props.searchTerm ||
nextProps.regexEnabled != this.props.regexEnabled ||
nextProps.bodySearchEnabled != this.props.bodySearchEnabled ||
!deepEqual(this.props.filters, nextProps.filters)
) {
this.setState({
@@ -112,6 +124,7 @@ class SearchableManagedTable extends PureComponent<Props, State> {
nextProps.filters,
nextProps.searchTerm,
nextProps.regexEnabled || false,
nextProps.bodySearchEnabled || false,
),
});
}

View File

@@ -55,6 +55,8 @@ export type TableBodyRow = {
highlightedBackgroundColor?: BackgroundColorProperty | undefined;
onDoubleClick?: (e: React.MouseEvent) => void;
copyText?: string;
requestBody?: string | null | undefined;
responseBody?: string | null | undefined;
highlightOnHover?: boolean;
columns: {
[key: string]: TableBodyColumn;