Skip to content

gRPC decoding

ProxyPro detects gRPC by sniffing Content-Type: application/grpc[+proto|+json|-web] on the response. Matching flows are reclassified to kind=grpc and the detail view gets a fourth tab labeled gRPC.

Native gRPC envelope

Each message in a gRPC stream has a 5-byte envelope:

1 byte compressed flag (0 = identity, 1 = gzip)
4 bytes payload length, big-endian uint32
N bytes payload (protobuf-encoded)

A unary RPC has one envelope. Server-streaming, client-streaming, and bidirectional RPCs concatenate multiple envelopes back-to-back.

The renderer parses these into a list of GrpcMessage records and displays them per request / response.

Per-message gzip

If grpc-encoding: gzip is set on the response, the renderer decompresses each envelope’s payload via the browser’s DecompressionStream before walking. (Engine-side gzip decode ships in P04.5.)

Heuristic protobuf walker

We don’t have your .proto file. The walker reads the wire format and recovers:

What we knowWhat we guess
Field number (1, 2, 3, …)
Wire type (varint, fixed64, length-delimited, fixed32)
Raw bytes”is this UTF-8 text?” — strict decode
“is this a nested message?” — re-walk
“is this binary blob?” — hex preview

For a varint field, value 0 or 1 is guessed as bool; otherwise varint. A length-delimited field is tried as a nested message first (recurse), then as UTF-8 string (strict decode), then falls back to binary.

Limits of heuristic decoding

  • Field names are unrecoverable without the .proto file. You see #1, #2, #3 instead of user_id, created_at, status.
  • Enums show as varints. You’ll see 2 instead of ROLE_ADMIN.
  • Packed repeated fields decode as length-delimited blobs that the walker may misclassify.
  • Fixed64 / fixed32 don’t distinguish signed vs unsigned vs float; we show them as unsigned.

Accuracy

In practice the walker handles ~85% of real-world gRPC payloads usefully. The “message vs string vs bytes” heuristic is the main failure mode — the strict UTF-8 decode catches most binary blobs, but ambiguous content (short ASCII-only binary) can show as text.

gRPC-Web

The detail view supports both binary application/grpc-web and base64 application/grpc-web-text bodies. It splits data messages from the in-band trailer frame and surfaces grpc-status / grpc-message; a truncated trailer is reported as unknown instead of being mistaken for success.

Named-field decoding

ProxyPro uses server reflection when the upstream exposes it:

  1. Server reflection — when the upstream gRPC server exposes grpc.reflection.v1alpha.ServerReflection, engine fetches descriptors and caches them. Subsequent flows decode with real field names.
  2. Fallback — without reflection, the heuristic wire walker remains available. Manual .proto upload is not currently implemented.

Reflection descriptors are cached per host; the heuristic walker is still useful for servers that intentionally disable reflection.

HTTP/3 downgrade

gRPC servers often advertise HTTP/3 via Alt-Svc. ProxyPro strips that header from every response so clients can’t switch to QUIC behind our back. See Configure the proxy.

See also