| # Encoding | |
| The gRPC API for sending and receiving is based upon *messages*. However, | |
| messages cannot be transmitted directly over a network; they must first be | |
| converted into *bytes*. This document describes how gRPC-Go converts messages | |
| into bytes and vice-versa for the purposes of network transmission. | |
| ## Codecs (Serialization and Deserialization) | |
| A `Codec` contains code to serialize a message into a byte slice (`Marshal`) and | |
| deserialize a byte slice back into a message (`Unmarshal`). `Codec`s are | |
| registered by name into a global registry maintained in the `encoding` package. | |
| ### Implementing a `Codec` | |
| A typical `Codec` will be implemented in its own package with an `init` function | |
| that registers itself, and is imported anonymously. For example: | |
| ```go | |
| package proto | |
| import "google.golang.org/grpc/encoding" | |
| func init() { | |
| encoding.RegisterCodec(protoCodec{}) | |
| } | |
| // ... implementation of protoCodec ... | |
| ``` | |
| For an example, gRPC's implementation of the `proto` codec can be found in | |
| [`encoding/proto`](https://godoc.org/google.golang.org/grpc/encoding/proto). | |
| ### Using a `Codec` | |
| By default, gRPC registers and uses the "proto" codec, so it is not necessary to | |
| do this in your own code to send and receive proto messages. To use another | |
| `Codec` from a client or server: | |
| ```go | |
| package myclient | |
| import _ "path/to/another/codec" | |
| ``` | |
| `Codec`s, by definition, must be symmetric, so the same desired `Codec` should | |
| be registered in both client and server binaries. | |
| On the client-side, to specify a `Codec` to use for message transmission, the | |
| `CallOption` `CallContentSubtype` should be used as follows: | |
| ```go | |
| response, err := myclient.MyCall(ctx, request, grpc.CallContentSubtype("mycodec")) | |
| ``` | |
| As a reminder, all `CallOption`s may be converted into `DialOption`s that become | |
| the default for all RPCs sent through a client using `grpc.WithDefaultCallOptions`: | |
| ```go | |
| myclient := grpc.NewClient(target, grpc.WithDefaultCallOptions(grpc.CallContentSubtype("mycodec"))) | |
| ``` | |
| When specified in either of these ways, messages will be encoded using this | |
| codec and sent along with headers indicating the codec (`content-type` set to | |
| `application/grpc+<codec name>`). | |
| On the server-side, using a `Codec` is as simple as registering it into the | |
| global registry (i.e. `import`ing it). If a message is encoded with the content | |
| sub-type supported by a registered `Codec`, it will be used automatically for | |
| decoding the request and encoding the response. Otherwise, for | |
| backward-compatibility reasons, gRPC will attempt to use the "proto" codec. In | |
| an upcoming change (tracked in [this | |
| issue](https://github.com/grpc/grpc-go/issues/1824)), such requests will be | |
| rejected with status code `Unimplemented` instead. | |
| ## Compressors (Compression and Decompression) | |
| Sometimes, the resulting serialization of a message is not space-efficient, and | |
| it may be beneficial to compress this byte stream before transmitting it over | |
| the network. To facilitate this operation, gRPC supports a mechanism for | |
| performing compression and decompression. | |
| A `Compressor` contains code to compress and decompress by wrapping `io.Writer`s | |
| and `io.Reader`s, respectively. (The form of `Compress` and `Decompress` were | |
| chosen to most closely match Go's standard package | |
| [implementations](https://golang.org/pkg/compress/) of compressors). Like | |
| `Codec`s, `Compressor`s are registered by name into a global registry maintained | |
| in the `encoding` package. | |
| ### Implementing a `Compressor` | |
| A typical `Compressor` will be implemented in its own package with an `init` | |
| function that registers itself, and is imported anonymously. For example: | |
| ```go | |
| package gzip | |
| import "google.golang.org/grpc/encoding" | |
| func init() { | |
| encoding.RegisterCompressor(compressor{}) | |
| } | |
| // ... implementation of compressor ... | |
| ``` | |
| An implementation of a `gzip` compressor can be found in | |
| [`encoding/gzip`](https://godoc.org/google.golang.org/grpc/encoding/gzip). | |
| ### Using a `Compressor` | |
| By default, gRPC does not register or use any compressors. To use a | |
| `Compressor` from a client or server: | |
| ```go | |
| package myclient | |
| import _ "google.golang.org/grpc/encoding/gzip" | |
| ``` | |
| `Compressor`s, by definition, must be symmetric, so the same desired | |
| `Compressor` should be registered in both client and server binaries. | |
| On the client-side, to specify a `Compressor` to use for message transmission, | |
| the `CallOption` `UseCompressor` should be used as follows: | |
| ```go | |
| response, err := myclient.MyCall(ctx, request, grpc.UseCompressor("gzip")) | |
| ``` | |
| As a reminder, all `CallOption`s may be converted into `DialOption`s that become | |
| the default for all RPCs sent through a client using `grpc.WithDefaultCallOptions`: | |
| ```go | |
| myclient := grpc.NewClient(target, grpc.WithDefaultCallOptions(grpc.UseCompressor("gzip"))) | |
| ``` | |
| When specified in either of these ways, messages will be compressed using this | |
| compressor and sent along with headers indicating the compressor | |
| (`content-coding` set to `<compressor name>`). | |
| On the server-side, using a `Compressor` is as simple as registering it into the | |
| global registry (i.e. `import`ing it). If a message is compressed with the | |
| content coding supported by a registered `Compressor`, it will be used | |
| automatically for decompressing the request and compressing the response. | |
| Otherwise, the request will be rejected with status code `Unimplemented`. |