# gRPC over HTTP2

## Introduction
This document serves as a detailed description for an implementation of gRPC carried over HTTP2 framing. It assumes familiarity with the HTTP2 specification.

## Protocol
Production rules are using ABNF syntax.

### Outline

The following is the general sequence of message atoms in a GRPC request & response message stream

* Request → Request-Headers *Length-Prefixed-Message EOS
* Response → (Response-Headers *Length-Prefixed-Message Trailers) / Trailers-Only


### Requests

* Request → Request-Headers *Length-Prefixed-Message EOS

Request-Headers are delivered as HTTP2 headers in HEADERS + CONTINUATION frames.

* **Request-Headers** → Call-Definition *Custom-Metadata
* **Call-Definition** → Method Scheme Path [Authority] TE [Timeout] Content-Type [Message-Type] [Message-Encoding] [Message-Accept-Encoding] [User-Agent]
* **Method** →  ":method POST"
* **Scheme** → ":scheme "  ("http" / "https")
* **Path** → ":path" "/" Service-Name "/" {method name}
* **Service-Name** → {IDL-specific service name}
* **Authority** → ":authority" {virtual host name of authority}
* **TE** → "te" "trailers"
* **Timeout** → "grpc-timeout" TimeoutValue TimeoutUnit
* **TimeoutValue** → {positive integer as ASCII string of at most 8 digits}
* **TimeoutUnit** → Hour / Minute / Second / Millisecond / Microsecond / Nanosecond
* **Content-Type** → "content-type" "application/grpc" [("+proto" / "+json" / {custom})]
* **Content-Coding** → "identity" / "gzip" / "deflate" / "snappy" / {custom}
* **Message-Encoding** → "grpc-encoding" Content-Coding
* **Message-Accept-Encoding** → "grpc-accept-encoding" Content-Coding *("," Content-Coding)
* **User-Agent** → "user-agent" {structured user-agent string}
* **Message-Type** → "grpc-message-type" {type name for message schema}
* **Custom-Metadata** → Binary-Header / ASCII-Header
* **Binary-Header** → {Header-Name "-bin" } {base64 encoded value}
* **ASCII-Header** → Header-Name ASCII-Value
* **Header-Name** → 1*( %x30-39 / %x61-7A / "_" / "-" / ".")
* **ASCII-Value** → 1*( %x20-%x7E )

HTTP2 requires that reserved headers, ones starting with ":" appear before all other headers. Additionally implementations should send **Timeout** immediately after the reserved headers and they should send the **Call-Definition** headers before sending **Custom-Metadata**.

If **Timeout** is omitted a server should assume an infinite timeout. Client implementations are free to send a default minimum timeout based on their deployment requirements.

If **Content-Type** does not begin with "application/grpc", gRPC servers SHOULD respond with HTTP status of 415 (Unsupported Media Type).

**Custom-Metadata** is an arbitrary set of key-value pairs defined by the application layer. Header names starting with "grpc-" but not listed here are reserved for future GRPC use and should not be used by applications as **Custom-Metadata**.

Binary header values must be encoded using Base64 as per https://tools.ietf.org/html/rfc4648#section-4. Implementations MUST accept padded and un-padded values and should emit un-padded values.

### Responses

* **Response** → (Response-Headers *Length-Prefixed-Message Trailers) / Trailers-Only
* **Response-Headers** → HTTP-Status [Message-Encoding] [Message-Accept-Encoding] Content-Type *Custom-Metadata
* **Trailers-Only** → HTTP-Status Content-Type Trailers
* **Trailers** → Status [Status-Message] [Status-Details] *Custom-Metadata
* **HTTP-Status** → ":status 200"
* **Status** → "grpc-status" 1*DIGIT
* **Status-Message** → "grpc-message" Percent-Encoded
* **Status-Details** → "grpc-status-details-bin" {base64 encoded value}
* **Percent-Encoded** → 1*(Percent-Byte-Unencoded / Percent-Byte-Encoded)
* **Percent-Byte-Unencoded** → 1*( %x20-%x24 / %x26-%x7E )
* **Percent-Byte-Encoded** → "%" 2HEXDIGIT

**Response-Headers** & **Trailers-Only** are each delivered in a single HTTP2 HEADERS frame block. Status must be sent in **Trailers** even if the status code is OK.

#### HTTP2 Transport Mapping

##### Stream Identification
All GRPC calls need to specify an internal ID. HTTP2 stream-ids are used as call identifiers.

##### Errors

The following mapping from RST_STREAM error codes to GRPC error codes is applied:

HTTP2 Code|GRPC Code
----------|-----------
NO_ERROR(0)|INTERNAL
PROTOCOL_ERROR(1)|INTERNAL
INTERNAL_ERROR(2)|INTERNAL
FLOW_CONTROL_ERROR(3)|INTERNAL
SETTINGS_TIMEOUT(4)|INTERNAL
REFUSED_STREAM|UNAVAILABLE
CANCEL(8)|Mapped to call cancellation when sent by a client. CANCELLED when sent by a server.
COMPRESSION_ERROR|INTERNAL
CONNECT_ERROR|INTERNAL
ENHANCE_YOUR_CALM|RESOURCE_EXHAUSTED
INADEQUATE_SECURITY|PERMISSION_DENIED

##### Security

The HTTP2 specification mandates the use of TLS 1.2 or higher when TLS is used with HTTP2.

##### Connection Management

###### GOAWAY Frame
Sent by servers to clients to indicate that they will no longer accept any new streams on the associated connections.

###### PING Frame
Both clients and servers can send a PING frame that the peer must respond to by precisely echoing what they received.

### Appendix A - GRPC for Protobuf

* **Service-Name** → ?( {proto package name} "." ) {service name}
* **Message-Type** → {fully qualified proto message name}
* **Content-Type** → "application/grpc+proto"
* **Status-Details** → {google.rpc.Status proto message}

---
Source: https://raw.githubusercontent.com/grpc/grpc/master/doc/PROTOCOL-HTTP2.md
Downloaded: 2026-06-07
