Add protobuf support to network inspector (#2080)
Summary: Protobuf based APIs are becoming more common (i.e. gRPC) but are difficult to inspect. Unlike plain text data formats (JSON), Protobuf calls transmit binary data requiring the format to be known ahead of time, making ad-hoc inspection impossible. This PR allows for those format definitions (messages in protobuf terminology) to be transmitted from the client to the network inspector plugin. These definitions are then imported into ProtobufJS which enables the binary data transmitted to be inspected as easily as JSON data. See Retrofit PR in https://github.com/facebook/flipper/pull/2084 ## Changelog * Add ProtobufJS library to network plugin * New `ProtobufFormatter` UI in `RequestDetails` * `ProtobufDefinitionsRepository` to cache and load protobuf defintions * `addProtobufDefinitions` call in the Android network plugin Pull Request resolved: https://github.com/facebook/flipper/pull/2080 Test Plan:  Reviewed By: mweststrate Differential Revision: D27507451 Pulled By: passy fbshipit-source-id: 586d891b74f2b17d28fe7a2a99074da755851f38
This commit is contained in:
committed by
Facebook GitHub Bot
parent
451c332260
commit
4d262c0da4
@@ -27,6 +27,8 @@ import React from 'react';
|
||||
|
||||
import querystring from 'querystring';
|
||||
import xmlBeautifier from 'xml-beautifier';
|
||||
import {ProtobufDefinitionsRepository} from './ProtobufDefinitionsRepository';
|
||||
import {Base64} from 'js-base64';
|
||||
|
||||
const WrappingText = styled(Text)({
|
||||
wordWrap: 'break-word',
|
||||
@@ -804,6 +806,75 @@ class BinaryFormatter {
|
||||
}
|
||||
}
|
||||
|
||||
class ProtobufFormatter {
|
||||
private protobufDefinitionRepository = ProtobufDefinitionsRepository.getInstance();
|
||||
|
||||
formatRequest(request: Request) {
|
||||
if (
|
||||
getHeaderValue(request.headers, 'content-type') ===
|
||||
'application/x-protobuf'
|
||||
) {
|
||||
const protobufDefinition = this.protobufDefinitionRepository.getRequestType(
|
||||
request.method,
|
||||
request.url,
|
||||
);
|
||||
if (protobufDefinition == undefined) {
|
||||
return (
|
||||
<Text>
|
||||
Could not locate protobuf definition for request body of{' '}
|
||||
{request.url}
|
||||
</Text>
|
||||
);
|
||||
}
|
||||
|
||||
if (request?.data) {
|
||||
const data = protobufDefinition.decode(
|
||||
Base64.toUint8Array(request.data),
|
||||
);
|
||||
return <JSONText>{data.toJSON()}</JSONText>;
|
||||
} else {
|
||||
return (
|
||||
<Text>Could not locate request body data for {request.url}</Text>
|
||||
);
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
formatResponse(request: Request, response: Response) {
|
||||
if (
|
||||
getHeaderValue(response.headers, 'content-type') ===
|
||||
'application/x-protobuf' ||
|
||||
request.url.endsWith('.proto')
|
||||
) {
|
||||
const protobufDefinition = this.protobufDefinitionRepository.getResponseType(
|
||||
request.method,
|
||||
request.url,
|
||||
);
|
||||
if (protobufDefinition == undefined) {
|
||||
return (
|
||||
<Text>
|
||||
Could not locate protobuf definition for response body of{' '}
|
||||
{request.url}
|
||||
</Text>
|
||||
);
|
||||
}
|
||||
|
||||
if (response?.data) {
|
||||
const data = protobufDefinition.decode(
|
||||
Base64.toUint8Array(response.data),
|
||||
);
|
||||
return <JSONText>{data.toJSON()}</JSONText>;
|
||||
} else {
|
||||
return (
|
||||
<Text>Could not locate response body data for {request.url}</Text>
|
||||
);
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
const BodyFormatters: Array<BodyFormatter> = [
|
||||
new ImageFormatter(),
|
||||
new VideoFormatter(),
|
||||
@@ -813,6 +884,7 @@ const BodyFormatters: Array<BodyFormatter> = [
|
||||
new JSONFormatter(),
|
||||
new FormUrlencodedFormatter(),
|
||||
new XMLTextFormatter(),
|
||||
new ProtobufFormatter(),
|
||||
new BinaryFormatter(),
|
||||
];
|
||||
|
||||
|
||||
Reference in New Issue
Block a user