Skip to content

Commit

Permalink
Handle gRPC compressed payloads
Browse files Browse the repository at this point in the history
  • Loading branch information
emaheuxPEREN committed Sep 24, 2024
1 parent f5ec9ee commit 3e73b1d
Showing 1 changed file with 20 additions and 4 deletions.
24 changes: 20 additions & 4 deletions src/util/protobuf.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import parseRawProto from 'rawprotoparse';
import { gunzipSync, inflateSync } from 'zlib';

const GZIP_MAGIC_BYTES = '1f8b';
const DEFLATE_MAGIC_BYTES = new Set<string>(['7801', '785e', '789c', '78da', '7820', '787d', '78bb', '78f9']);

export function isProbablyProtobuf(input: Uint8Array) {
// Protobuf data starts with a varint, consisting of a field
Expand Down Expand Up @@ -38,12 +42,24 @@ export const extractProtobufFromGrpc = (input: Buffer) => {
const protobufMessasges: Buffer[] = [];

while (input.length > 0) {
if (input.readInt8() != 0) {
throw new Error("Compressed gRPC messages not yet supported")
const compressionFlag = input.readInt8();
const length = input.readInt32BE(1);
let message = input.slice(5, 5 + length);

if (compressionFlag != 0) {
// TODO: In theory we should check consistency of actual content encoding
// with 'grpc-encoding' header, but we do not have access to it in this context
const magicBytes = message.toString('hex', 0, 2);
if (magicBytes == GZIP_MAGIC_BYTES) {
message = gunzipSync(message);
} else if (DEFLATE_MAGIC_BYTES.has(magicBytes)) {
message = inflateSync(message);
} else {
throw new Error(`Unknown gRPC compression scheme, magic bytes = '${magicBytes}'`);
}
}

const length = input.readInt32BE(1);
protobufMessasges.push(input.slice(5, 5 + length));
protobufMessasges.push(message);
input = input.subarray(5 + length);
}

Expand Down

0 comments on commit 3e73b1d

Please sign in to comment.