1*cc02d7e2SAndroid Build Coastguard Worker## gRPC Compression 2*cc02d7e2SAndroid Build Coastguard Worker 3*cc02d7e2SAndroid Build Coastguard WorkerThe keywords "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", 4*cc02d7e2SAndroid Build Coastguard Worker"SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be 5*cc02d7e2SAndroid Build Coastguard Workerinterpreted as described in [RFC 2119](http://www.ietf.org/rfc/rfc2119.txt). 6*cc02d7e2SAndroid Build Coastguard Worker 7*cc02d7e2SAndroid Build Coastguard Worker### Intent 8*cc02d7e2SAndroid Build Coastguard Worker 9*cc02d7e2SAndroid Build Coastguard WorkerCompression is used to reduce the amount of bandwidth used between peers. The 10*cc02d7e2SAndroid Build Coastguard Workercompression supported by gRPC acts _at the individual message level_, taking 11*cc02d7e2SAndroid Build Coastguard Worker_message_ [as defined in the wire format 12*cc02d7e2SAndroid Build Coastguard Workerdocument](PROTOCOL-HTTP2.md). 13*cc02d7e2SAndroid Build Coastguard Worker 14*cc02d7e2SAndroid Build Coastguard WorkerThe implementation supports different compression algorithms. A _default 15*cc02d7e2SAndroid Build Coastguard Workercompression level_, to be used in the absence of message-specific settings, MAY 16*cc02d7e2SAndroid Build Coastguard Workerbe specified for during channel creation. 17*cc02d7e2SAndroid Build Coastguard Worker 18*cc02d7e2SAndroid Build Coastguard WorkerThe ability to control compression settings per call and to enable/disable 19*cc02d7e2SAndroid Build Coastguard Workercompression on a per message basis MAY be used to prevent CRIME/BEAST attacks. 20*cc02d7e2SAndroid Build Coastguard WorkerIt also allows for asymmetric compression communication, whereby a response MAY 21*cc02d7e2SAndroid Build Coastguard Workerbe compressed differently, if at all. 22*cc02d7e2SAndroid Build Coastguard Worker 23*cc02d7e2SAndroid Build Coastguard Worker### Specification 24*cc02d7e2SAndroid Build Coastguard Worker 25*cc02d7e2SAndroid Build Coastguard WorkerCompression MAY be configured by the Client Application by calling the 26*cc02d7e2SAndroid Build Coastguard Workerappropriate API method. There are two scenarios where compression MAY be 27*cc02d7e2SAndroid Build Coastguard Workerconfigured: 28*cc02d7e2SAndroid Build Coastguard Worker 29*cc02d7e2SAndroid Build Coastguard Worker+ At channel creation time, which sets the channel default compression and 30*cc02d7e2SAndroid Build Coastguard Worker therefore the compression that SHALL be used in the absence of per-RPC 31*cc02d7e2SAndroid Build Coastguard Worker compression configuration. 32*cc02d7e2SAndroid Build Coastguard Worker+ At response time, via: 33*cc02d7e2SAndroid Build Coastguard Worker + For unary RPCs, the {Client,Server}Context instance. 34*cc02d7e2SAndroid Build Coastguard Worker + For streaming RPCs, the {Client,Server}Writer instance. In this case, 35*cc02d7e2SAndroid Build Coastguard Worker configuration is reduced to disabling compression altogether. 36*cc02d7e2SAndroid Build Coastguard Worker 37*cc02d7e2SAndroid Build Coastguard Worker### Compression Method Asymmetry Between Peers 38*cc02d7e2SAndroid Build Coastguard Worker 39*cc02d7e2SAndroid Build Coastguard WorkerA gRPC peer MAY choose to respond using a different compression method to that 40*cc02d7e2SAndroid Build Coastguard Workerof the request, including not performing any compression, regardless of channel 41*cc02d7e2SAndroid Build Coastguard Workerand RPC settings (for example, if compression would result in small or negative 42*cc02d7e2SAndroid Build Coastguard Workergains). 43*cc02d7e2SAndroid Build Coastguard Worker 44*cc02d7e2SAndroid Build Coastguard WorkerIf a client message is compressed by an algorithm that is not supported 45*cc02d7e2SAndroid Build Coastguard Workerby a server, the message WILL result in an `UNIMPLEMENTED` error status on the 46*cc02d7e2SAndroid Build Coastguard Workerserver. The server will then include a `grpc-accept-encoding` response 47*cc02d7e2SAndroid Build Coastguard Workerheader which specifies the algorithms that the server accepts. If the client 48*cc02d7e2SAndroid Build Coastguard Workermessage is compressed using one of the algorithms from the `grpc-accept-encoding` header 49*cc02d7e2SAndroid Build Coastguard Workerand an `UNIMPLEMENTED` error status is returned from the server, the cause of the error 50*cc02d7e2SAndroid Build Coastguard WorkerMUST NOT be related to compression. If a server sent data which is compressed by an algorithm 51*cc02d7e2SAndroid Build Coastguard Workerthat is not supported by the client, an `INTERNAL` error status will occur on the client side. 52*cc02d7e2SAndroid Build Coastguard Worker 53*cc02d7e2SAndroid Build Coastguard WorkerNote that a peer MAY choose to not disclose all the encodings it supports. 54*cc02d7e2SAndroid Build Coastguard WorkerHowever, if it receives a message compressed in an undisclosed but supported 55*cc02d7e2SAndroid Build Coastguard Workerencoding, it MUST include said encoding in the response's `grpc-accept-encoding` 56*cc02d7e2SAndroid Build Coastguard Workerheader. 57*cc02d7e2SAndroid Build Coastguard Worker 58*cc02d7e2SAndroid Build Coastguard WorkerFor every message a server is requested to compress using an algorithm it knows 59*cc02d7e2SAndroid Build Coastguard Workerthe client doesn't support (as indicated by the last `grpc-accept-encoding` 60*cc02d7e2SAndroid Build Coastguard Workerheader received from the client), it SHALL send the message uncompressed. 61*cc02d7e2SAndroid Build Coastguard Worker 62*cc02d7e2SAndroid Build Coastguard Worker### Specific Disabling of Compression 63*cc02d7e2SAndroid Build Coastguard Worker 64*cc02d7e2SAndroid Build Coastguard WorkerIf the user (through the previously described mechanisms) requests to disable 65*cc02d7e2SAndroid Build Coastguard Workercompression the next message MUST be sent uncompressed. This is instrumental in 66*cc02d7e2SAndroid Build Coastguard Workerpreventing BEAST/CRIME attacks. This applies to both the unary and streaming 67*cc02d7e2SAndroid Build Coastguard Workercases. 68*cc02d7e2SAndroid Build Coastguard Worker 69*cc02d7e2SAndroid Build Coastguard Worker### Compression Levels and Algorithms 70*cc02d7e2SAndroid Build Coastguard Worker 71*cc02d7e2SAndroid Build Coastguard WorkerThe set of supported algorithm is implementation dependent. In order to simplify 72*cc02d7e2SAndroid Build Coastguard Workerthe public API and to operate seamlessly across implementations (both in terms 73*cc02d7e2SAndroid Build Coastguard Workerof languages but also different version of the same one), we introduce the idea 74*cc02d7e2SAndroid Build Coastguard Workerof _compression levels_ (such as "low", "medium", "high"). 75*cc02d7e2SAndroid Build Coastguard Worker 76*cc02d7e2SAndroid Build Coastguard WorkerLevels map to concrete algorithms and/or their settings (such as "low" mapping 77*cc02d7e2SAndroid Build Coastguard Workerto "gzip -3" and "high" mapping to "gzip -9") automatically depending on what a 78*cc02d7e2SAndroid Build Coastguard Workerpeer is known to support. A server is always aware of what its clients support, 79*cc02d7e2SAndroid Build Coastguard Workeras clients disclose it in the Message-Accept-Encoding header as part of the 80*cc02d7e2SAndroid Build Coastguard WorkerRPC. A client doesn't a priori (presently) know which algorithms a 81*cc02d7e2SAndroid Build Coastguard Workerserver supports. This issue can be addressed with an initial negotiation of 82*cc02d7e2SAndroid Build Coastguard Workercapabilities or an automatic retry mechanism. These features will be implemented 83*cc02d7e2SAndroid Build Coastguard Workerin the future. Currently however, compression levels are only supported at the 84*cc02d7e2SAndroid Build Coastguard Workerserver side, which is aware of the client's capabilities through the incoming 85*cc02d7e2SAndroid Build Coastguard WorkerMessage-Accept-Encoding header. 86*cc02d7e2SAndroid Build Coastguard Worker 87*cc02d7e2SAndroid Build Coastguard Worker### Propagation to child RPCs 88*cc02d7e2SAndroid Build Coastguard Worker 89*cc02d7e2SAndroid Build Coastguard WorkerThe inheritance of the compression configuration by child RPCs is left up to the 90*cc02d7e2SAndroid Build Coastguard Workerimplementation. Note that in the absence of changes to the parent channel, its 91*cc02d7e2SAndroid Build Coastguard Workerconfiguration will be used. 92*cc02d7e2SAndroid Build Coastguard Worker 93*cc02d7e2SAndroid Build Coastguard Worker### Deflate Compression 94*cc02d7e2SAndroid Build Coastguard Worker 95*cc02d7e2SAndroid Build Coastguard WorkerLike HTTP implementations, gRPC implementations MUST use the "deflate" 96*cc02d7e2SAndroid Build Coastguard Workercompression to mean the zlib structure (defined in 97*cc02d7e2SAndroid Build Coastguard Worker[RFC 1950](https://datatracker.ietf.org/doc/html/rfc1950)) 98*cc02d7e2SAndroid Build Coastguard Workerwith the deflate compression algorithm (defined in 99*cc02d7e2SAndroid Build Coastguard Worker[RFC 1951](https://datatracker.ietf.org/doc/html/rfc1951)). 100*cc02d7e2SAndroid Build Coastguard WorkerServers and clients MUST NOT send raw deflate data. 101*cc02d7e2SAndroid Build Coastguard Worker 102*cc02d7e2SAndroid Build Coastguard Worker### Test cases 103*cc02d7e2SAndroid Build Coastguard Worker 104*cc02d7e2SAndroid Build Coastguard Worker1. When a compression level is not specified for either the channel or the 105*cc02d7e2SAndroid Build Coastguard Workermessage, the default channel level _none_ is considered: data MUST NOT be 106*cc02d7e2SAndroid Build Coastguard Workercompressed. 107*cc02d7e2SAndroid Build Coastguard Worker1. When per-RPC compression configuration isn't present for a message, the 108*cc02d7e2SAndroid Build Coastguard Workerchannel compression configuration MUST be used. 109*cc02d7e2SAndroid Build Coastguard Worker1. When a compression method (including no compression) is specified for an 110*cc02d7e2SAndroid Build Coastguard Workeroutgoing message, the message MUST be compressed accordingly. 111*cc02d7e2SAndroid Build Coastguard Worker1. A message compressed by a client in a way not supported by its server MUST 112*cc02d7e2SAndroid Build Coastguard Workerfail with status `UNIMPLEMENTED`, its associated description indicating the 113*cc02d7e2SAndroid Build Coastguard Workerunsupported condition as well as the supported ones. The returned 114*cc02d7e2SAndroid Build Coastguard Worker`grpc-accept-encoding` header MUST NOT contain the compression method 115*cc02d7e2SAndroid Build Coastguard Worker(encoding) used. 116*cc02d7e2SAndroid Build Coastguard Worker1. A message compressed by a server in a way not supported by its client MUST 117*cc02d7e2SAndroid Build Coastguard Workerfail with status `INTERNAL`, its associated description indicating the 118*cc02d7e2SAndroid Build Coastguard Workerunsupported condition as well as the supported ones. The returned 119*cc02d7e2SAndroid Build Coastguard Worker`grpc-accept-encoding` header MUST NOT contain the compression method 120*cc02d7e2SAndroid Build Coastguard Worker(encoding) used. 121*cc02d7e2SAndroid Build Coastguard Worker1. An ill-constructed message with its [Compressed-Flag 122*cc02d7e2SAndroid Build Coastguard Workerbit](PROTOCOL-HTTP2.md#compressed-flag) 123*cc02d7e2SAndroid Build Coastguard Workerset but lacking a 124*cc02d7e2SAndroid Build Coastguard Worker[grpc-encoding](PROTOCOL-HTTP2.md#message-encoding) 125*cc02d7e2SAndroid Build Coastguard Workerentry different from _identity_ in its metadata MUST fail with `INTERNAL` 126*cc02d7e2SAndroid Build Coastguard Workerstatus, its associated description indicating the invalid Compressed-Flag 127*cc02d7e2SAndroid Build Coastguard Workercondition. 128