| # 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.Dial(ctx, 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.Dial(ctx, target, grpc.WithDefaultCallOptions(grpc.UseCompresor("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`. |