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:
committed by
Facebook Github Bot
parent
691a4ee135
commit
faaf8c4f32
@@ -283,8 +283,11 @@ ${request.headers
|
|||||||
)
|
)
|
||||||
.join('\n')}`;
|
.join('\n')}`;
|
||||||
|
|
||||||
if (request.data) {
|
const requestData = request.data ? decodeBody(request) : null;
|
||||||
copyText += `\n\n${decodeBody(request)}`;
|
const responseData = response && response.data ? decodeBody(response) : null;
|
||||||
|
|
||||||
|
if (requestData) {
|
||||||
|
copyText += `\n\n${requestData}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (response) {
|
if (response) {
|
||||||
@@ -300,8 +303,8 @@ ${response.headers
|
|||||||
.join('\n')}`;
|
.join('\n')}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (response) {
|
if (responseData) {
|
||||||
copyText += `\n\n${decodeBody(response)}`;
|
copyText += `\n\n${responseData}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -346,6 +349,8 @@ ${response.headers
|
|||||||
sortKey: request.timestamp,
|
sortKey: request.timestamp,
|
||||||
copyText,
|
copyText,
|
||||||
highlightOnHover: true,
|
highlightOnHover: true,
|
||||||
|
requestBody: requestData,
|
||||||
|
responseBody: responseData,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -471,6 +476,7 @@ class NetworkTable extends PureComponent<NetworkTableProps, NetworkTableState> {
|
|||||||
highlightedRows={this.props.highlightedRows}
|
highlightedRows={this.props.highlightedRows}
|
||||||
rowLineHeight={26}
|
rowLineHeight={26}
|
||||||
allowRegexSearch={true}
|
allowRegexSearch={true}
|
||||||
|
allowBodySearch={true}
|
||||||
zebra={false}
|
zebra={false}
|
||||||
actions={<Button onClick={this.props.clear}>Clear Table</Button>}
|
actions={<Button onClick={this.props.clear}>Clear Table</Button>}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ type Props = {
|
|||||||
toggled?: boolean;
|
toggled?: boolean;
|
||||||
className?: string;
|
className?: string;
|
||||||
label?: string;
|
label?: string;
|
||||||
|
tooltip?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -71,7 +72,7 @@ type Props = {
|
|||||||
export default class ToggleButton extends React.Component<Props> {
|
export default class ToggleButton extends React.Component<Props> {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<Container onClick={this.props.onClick}>
|
<Container onClick={this.props.onClick} title={this.props.tooltip}>
|
||||||
<StyledButton
|
<StyledButton
|
||||||
className={this.props.className}
|
className={this.props.className}
|
||||||
toggled={this.props.toggled || false}
|
toggled={this.props.toggled || false}
|
||||||
|
|||||||
@@ -93,7 +93,9 @@ export type SearchableProps = {
|
|||||||
searchTerm: string;
|
searchTerm: string;
|
||||||
filters: Array<Filter>;
|
filters: Array<Filter>;
|
||||||
allowRegexSearch?: boolean;
|
allowRegexSearch?: boolean;
|
||||||
|
allowBodySearch?: boolean;
|
||||||
regexEnabled?: boolean;
|
regexEnabled?: boolean;
|
||||||
|
bodySearchEnabled?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@@ -104,6 +106,7 @@ type Props = {
|
|||||||
onFilterChange: (filters: Array<Filter>) => void;
|
onFilterChange: (filters: Array<Filter>) => void;
|
||||||
defaultFilters: Array<Filter>;
|
defaultFilters: Array<Filter>;
|
||||||
allowRegexSearch: boolean;
|
allowRegexSearch: boolean;
|
||||||
|
allowBodySearch: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
type State = {
|
type State = {
|
||||||
@@ -112,6 +115,7 @@ type State = {
|
|||||||
searchTerm: string;
|
searchTerm: string;
|
||||||
hasFocus: boolean;
|
hasFocus: boolean;
|
||||||
regexEnabled: boolean;
|
regexEnabled: boolean;
|
||||||
|
bodySearchEnabled: boolean;
|
||||||
compiledRegex: RegExp | null | undefined;
|
compiledRegex: RegExp | null | undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -137,6 +141,7 @@ const Searchable = (
|
|||||||
searchTerm: '',
|
searchTerm: '',
|
||||||
hasFocus: false,
|
hasFocus: false,
|
||||||
regexEnabled: false,
|
regexEnabled: false,
|
||||||
|
bodySearchEnabled: false,
|
||||||
compiledRegex: null,
|
compiledRegex: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -149,6 +154,7 @@ const Searchable = (
|
|||||||
| {
|
| {
|
||||||
filters: Array<Filter>;
|
filters: Array<Filter>;
|
||||||
regexEnabled?: boolean;
|
regexEnabled?: boolean;
|
||||||
|
bodySearchEnabled?: boolean;
|
||||||
searchTerm?: string;
|
searchTerm?: string;
|
||||||
}
|
}
|
||||||
| undefined;
|
| undefined;
|
||||||
@@ -192,6 +198,8 @@ const Searchable = (
|
|||||||
searchTerm: searchTerm,
|
searchTerm: searchTerm,
|
||||||
filters: savedState.filters || this.state.filters,
|
filters: savedState.filters || this.state.filters,
|
||||||
regexEnabled: savedState.regexEnabled || this.state.regexEnabled,
|
regexEnabled: savedState.regexEnabled || this.state.regexEnabled,
|
||||||
|
bodySearchEnabled:
|
||||||
|
savedState.bodySearchEnabled || this.state.bodySearchEnabled,
|
||||||
compiledRegex: compileRegex(searchTerm),
|
compiledRegex: compileRegex(searchTerm),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -202,6 +210,7 @@ const Searchable = (
|
|||||||
this.getTableKey() &&
|
this.getTableKey() &&
|
||||||
(prevState.searchTerm !== this.state.searchTerm ||
|
(prevState.searchTerm !== this.state.searchTerm ||
|
||||||
prevState.regexEnabled != this.state.regexEnabled ||
|
prevState.regexEnabled != this.state.regexEnabled ||
|
||||||
|
prevState.bodySearchEnabled != this.state.bodySearchEnabled ||
|
||||||
prevState.filters !== this.state.filters)
|
prevState.filters !== this.state.filters)
|
||||||
) {
|
) {
|
||||||
window.localStorage.setItem(
|
window.localStorage.setItem(
|
||||||
@@ -210,6 +219,7 @@ const Searchable = (
|
|||||||
searchTerm: this.state.searchTerm,
|
searchTerm: this.state.searchTerm,
|
||||||
filters: this.state.filters,
|
filters: this.state.filters,
|
||||||
regexEnabled: this.state.regexEnabled,
|
regexEnabled: this.state.regexEnabled,
|
||||||
|
bodySearchEnabled: this.state.bodySearchEnabled,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
if (this.props.onFilterChange != null) {
|
if (this.props.onFilterChange != null) {
|
||||||
@@ -406,6 +416,12 @@ const Searchable = (
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
onBodySearchToggled = () => {
|
||||||
|
this.setState({
|
||||||
|
bodySearchEnabled: !this.state.bodySearchEnabled,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
hasFocus = (): boolean => {
|
hasFocus = (): boolean => {
|
||||||
return this.state.focusedToken !== -1 || this.state.hasFocus;
|
return this.state.focusedToken !== -1 || this.state.hasFocus;
|
||||||
};
|
};
|
||||||
@@ -464,6 +480,16 @@ const Searchable = (
|
|||||||
label={'Regex'}
|
label={'Regex'}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : 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) && (
|
{(this.state.searchTerm || this.state.filters.length > 0) && (
|
||||||
<Clear onClick={this.clear}>×</Clear>
|
<Clear onClick={this.clear}>×</Clear>
|
||||||
)}
|
)}
|
||||||
@@ -475,6 +501,7 @@ const Searchable = (
|
|||||||
addFilter={this.addFilter}
|
addFilter={this.addFilter}
|
||||||
searchTerm={this.state.searchTerm}
|
searchTerm={this.state.searchTerm}
|
||||||
regexEnabled={this.state.regexEnabled}
|
regexEnabled={this.state.regexEnabled}
|
||||||
|
bodySearchEnabled={this.state.bodySearchEnabled}
|
||||||
filters={this.state.filters}
|
filters={this.state.filters}
|
||||||
/>,
|
/>,
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ function rowMatchesRegex(values: Array<string>, regex: string): boolean {
|
|||||||
function rowMatchesSearchTerm(
|
function rowMatchesSearchTerm(
|
||||||
searchTerm: string,
|
searchTerm: string,
|
||||||
isRegex: boolean,
|
isRegex: boolean,
|
||||||
|
isBodySearchEnabled: boolean,
|
||||||
row: TableBodyRow,
|
row: TableBodyRow,
|
||||||
): boolean {
|
): boolean {
|
||||||
if (searchTerm == null || searchTerm.length === 0) {
|
if (searchTerm == null || searchTerm.length === 0) {
|
||||||
@@ -68,6 +69,14 @@ function rowMatchesSearchTerm(
|
|||||||
const rowValues = Object.keys(row.columns).map(key =>
|
const rowValues = Object.keys(row.columns).map(key =>
|
||||||
textContent(row.columns[key].value),
|
textContent(row.columns[key].value),
|
||||||
);
|
);
|
||||||
|
if (isBodySearchEnabled) {
|
||||||
|
if (row.requestBody) {
|
||||||
|
rowValues.push(row.requestBody);
|
||||||
|
}
|
||||||
|
if (row.responseBody) {
|
||||||
|
rowValues.push(row.responseBody);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (isRegex) {
|
if (isRegex) {
|
||||||
return rowMatchesRegex(rowValues, searchTerm);
|
return rowMatchesRegex(rowValues, searchTerm);
|
||||||
}
|
}
|
||||||
@@ -80,9 +89,10 @@ const filterRowsFactory = (
|
|||||||
filters: Array<Filter>,
|
filters: Array<Filter>,
|
||||||
searchTerm: string,
|
searchTerm: string,
|
||||||
regexSearch: boolean,
|
regexSearch: boolean,
|
||||||
|
bodySearch: boolean,
|
||||||
) => (row: TableBodyRow): boolean =>
|
) => (row: TableBodyRow): boolean =>
|
||||||
rowMatchesFilters(filters, row) &&
|
rowMatchesFilters(filters, row) &&
|
||||||
rowMatchesSearchTerm(searchTerm, regexSearch, row);
|
rowMatchesSearchTerm(searchTerm, regexSearch, bodySearch, row);
|
||||||
|
|
||||||
class SearchableManagedTable extends PureComponent<Props, State> {
|
class SearchableManagedTable extends PureComponent<Props, State> {
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
@@ -94,6 +104,7 @@ class SearchableManagedTable extends PureComponent<Props, State> {
|
|||||||
this.props.filters,
|
this.props.filters,
|
||||||
this.props.searchTerm,
|
this.props.searchTerm,
|
||||||
this.props.regexEnabled || false,
|
this.props.regexEnabled || false,
|
||||||
|
this.props.bodySearchEnabled || false,
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -105,6 +116,7 @@ class SearchableManagedTable extends PureComponent<Props, State> {
|
|||||||
if (
|
if (
|
||||||
nextProps.searchTerm !== this.props.searchTerm ||
|
nextProps.searchTerm !== this.props.searchTerm ||
|
||||||
nextProps.regexEnabled != this.props.regexEnabled ||
|
nextProps.regexEnabled != this.props.regexEnabled ||
|
||||||
|
nextProps.bodySearchEnabled != this.props.bodySearchEnabled ||
|
||||||
!deepEqual(this.props.filters, nextProps.filters)
|
!deepEqual(this.props.filters, nextProps.filters)
|
||||||
) {
|
) {
|
||||||
this.setState({
|
this.setState({
|
||||||
@@ -112,6 +124,7 @@ class SearchableManagedTable extends PureComponent<Props, State> {
|
|||||||
nextProps.filters,
|
nextProps.filters,
|
||||||
nextProps.searchTerm,
|
nextProps.searchTerm,
|
||||||
nextProps.regexEnabled || false,
|
nextProps.regexEnabled || false,
|
||||||
|
nextProps.bodySearchEnabled || false,
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,6 +55,8 @@ export type TableBodyRow = {
|
|||||||
highlightedBackgroundColor?: BackgroundColorProperty | undefined;
|
highlightedBackgroundColor?: BackgroundColorProperty | undefined;
|
||||||
onDoubleClick?: (e: React.MouseEvent) => void;
|
onDoubleClick?: (e: React.MouseEvent) => void;
|
||||||
copyText?: string;
|
copyText?: string;
|
||||||
|
requestBody?: string | null | undefined;
|
||||||
|
responseBody?: string | null | undefined;
|
||||||
highlightOnHover?: boolean;
|
highlightOnHover?: boolean;
|
||||||
columns: {
|
columns: {
|
||||||
[key: string]: TableBodyColumn;
|
[key: string]: TableBodyColumn;
|
||||||
|
|||||||
Reference in New Issue
Block a user