diff --git a/desktop/plugins/network/RequestDetails.tsx b/desktop/plugins/network/RequestDetails.tsx
index 0c2e5e78b..e48e5e1e5 100644
--- a/desktop/plugins/network/RequestDetails.tsx
+++ b/desktop/plugins/network/RequestDetails.tsx
@@ -19,6 +19,7 @@ import {
Select,
styled,
colors,
+ SmallText,
} from 'flipper';
import {decodeBody, getHeaderValue} from './utils';
import {formatBytes} from './index';
@@ -332,14 +333,23 @@ class RequestBodyInspector extends Component<{
}> {
render() {
const {request, formattedText} = this.props;
+ if (request.data == null || request.data.trim() === '') {
+ return ;
+ }
const bodyFormatters = formattedText ? TextBodyFormatters : BodyFormatters;
- let component;
for (const formatter of bodyFormatters) {
if (formatter.formatRequest) {
try {
- component = formatter.formatRequest(request);
+ const component = formatter.formatRequest(request);
if (component) {
- break;
+ return (
+
+ {component}
+
+ Formatted by {formatter.constructor.name}
+
+
+ );
}
} catch (e) {
console.warn(
@@ -349,10 +359,7 @@ class RequestBodyInspector extends Component<{
}
}
}
-
- component = component || {decodeBody(request)};
-
- return {component};
+ return renderRawBody(request);
}
}
@@ -363,14 +370,23 @@ class ResponseBodyInspector extends Component<{
}> {
render() {
const {request, response, formattedText} = this.props;
+ if (response.data == null || response.data.trim() === '') {
+ return ;
+ }
const bodyFormatters = formattedText ? TextBodyFormatters : BodyFormatters;
- let component;
for (const formatter of bodyFormatters) {
if (formatter.formatResponse) {
try {
- component = formatter.formatResponse(request, response);
+ const component = formatter.formatResponse(request, response);
if (component) {
- break;
+ return (
+
+ {component}
+
+ Formatted by {formatter.constructor.name}
+
+
+ );
}
} catch (e) {
console.warn(
@@ -380,13 +396,43 @@ class ResponseBodyInspector extends Component<{
}
}
}
-
- component = component || {decodeBody(response)};
-
- return {component};
+ return renderRawBody(response);
}
}
+const FormattedBy = styled(SmallText)({
+ marginTop: 8,
+ fontSize: '0.7em',
+ textAlign: 'center',
+ display: 'block',
+});
+
+const Empty = () => (
+
+ (empty)
+
+);
+
+function renderRawBody(container: Request | Response) {
+ const decoded = decodeBody(container);
+ return (
+
+ {decoded ? (
+
+ {decoded}
+
+ ) : (
+ <>
+ (Failed to decode)
+
+ {container.data}
+
+ >
+ )}
+
+ );
+}
+
const MediaContainer = styled(FlexColumn)({
alignItems: 'center',
justifyContent: 'center',
@@ -662,7 +708,11 @@ class GraphQLFormatter {
};
formatRequest = (request: Request) => {
if (request.url.indexOf('graphql') > 0) {
- const data = querystring.parse(decodeBody(request));
+ const decoded = decodeBody(request);
+ if (!decoded) {
+ return undefined;
+ }
+ const data = querystring.parse(decoded);
if (typeof data.variables === 'string') {
data.variables = JSON.parse(data.variables);
}
@@ -725,16 +775,40 @@ class FormUrlencodedFormatter {
formatRequest = (request: Request) => {
const contentType = getHeaderValue(request.headers, 'content-type');
if (contentType.startsWith('application/x-www-form-urlencoded')) {
+ const decoded = decodeBody(request);
+ if (!decoded) {
+ return undefined;
+ }
return (
);
}
};
}
+class BinaryFormatter {
+ formatRequest(request: Request) {
+ return this.format(request);
+ }
+
+ formatResponse(_request: Request, response: Response) {
+ return this.format(response);
+ }
+
+ format(container: Request | Response) {
+ if (
+ getHeaderValue(container.headers, 'content-type') ===
+ 'application/octet-stream'
+ ) {
+ return '(binary data)'; // we could offer a download button here?
+ }
+ return undefined;
+ }
+}
+
const BodyFormatters: Array = [
new ImageFormatter(),
new VideoFormatter(),
@@ -744,6 +818,7 @@ const BodyFormatters: Array = [
new JSONFormatter(),
new FormUrlencodedFormatter(),
new XMLTextFormatter(),
+ new BinaryFormatter(),
];
const TextBodyFormatters: Array = [new JSONTextFormatter()];
diff --git a/desktop/plugins/network/utils.tsx b/desktop/plugins/network/utils.tsx
index 0de72428e..a5cd2c64d 100644
--- a/desktop/plugins/network/utils.tsx
+++ b/desktop/plugins/network/utils.tsx
@@ -33,7 +33,9 @@ export function decodeBody(container: Request | Response): string {
return b64Decoded;
} catch (e) {
- console.warn('Discarding malformed body, size: ' + b64Decoded.length);
+ console.warn(
+ `Flipper failed to decode request/response body (size: ${b64Decoded.length}): ${e}`,
+ );
return '';
}
}
@@ -52,6 +54,9 @@ function decompress(body: string): string {
} catch (e) {
// Sometimes Content-Encoding is 'gzip' but the body is already decompressed.
// Assume this is the case when decompression fails.
+ if (!('' + e).includes('incorrect header check')) {
+ console.warn('decompression failed: ' + e);
+ }
}
return body;