Expand description
HTTP/2 gRPC frame parsing for client streaming support
This module provides parsing of gRPC messages from HTTP/2 request bodies. gRPC frames are structured according to RFC 9109 (gRPC over HTTP/2):
+----------+----------+-+-+-+-+-+-+-+-+
|Compression| Length |
| Flags (1) | (4 bytes) |
+----------+----------+-+-+-+-+-+-+-+-+-+-+
| |
| Serialized Message (N bytes) |
| |
+-------------------------------------+The compression flag indicates whether the message is compressed (1 = compressed, 0 = uncompressed). The length is encoded as a big-endian u32, indicating the size of the message bytes.
§Protocol Details
- Compression Flag: 1 byte, value 0 or 1
- Message Length: 4 bytes, big-endian u32, maximum 4GB
- Message Data: N bytes, where N is the length from the header
§Stream Processing
The parser processes the HTTP/2 body stream by:
- Reading the 5-byte frame header (compression flag + length)
- Parsing the length as big-endian u32
- Validating the length against
max_message_size - Reading the message bytes
- Yielding the message
- Repeating until the body is exhausted
§Error Handling
The parser returns gRPC status codes according to RFC 9110:
INTERNAL: Protocol parsing errors (incomplete frames, read errors)RESOURCE_EXHAUSTED: Message size exceeds limitUNIMPLEMENTED: Compression requested (not supported)
§Example
ⓘ
use spikard_http::grpc::framing::parse_grpc_client_stream;
use axum::body::Body;
use bytes::Bytes;
use futures_util::StreamExt;
let body = Body::from("...");
let max_size = 4 * 1024 * 1024; // 4MB
let mut stream = parse_grpc_client_stream(body, max_size).await?;
while let Some(result) = stream.next().await {
match result {
Ok(message) => println!("Message: {:?}", message),
Err(status) => eprintln!("Error: {}", status),
}
}Functions§
- parse_
grpc_ client_ stream - Parses an HTTP/2 gRPC request body as a stream of messages