OSDN Git Service

new repo
[bytom/vapor.git] / vendor / google.golang.org / grpc / Documentation / grpc-metadata.md
1 # Metadata
2
3 gRPC supports sending metadata between client and server.
4 This doc shows how to send and receive metadata in gRPC-go.
5
6 ## Background
7
8 Four kinds of service method:
9
10 - [Unary RPC](https://grpc.io/docs/guides/concepts.html#unary-rpc)
11 - [Server streaming RPC](https://grpc.io/docs/guides/concepts.html#server-streaming-rpc)
12 - [Client streaming RPC](https://grpc.io/docs/guides/concepts.html#client-streaming-rpc)
13 - [Bidirectional streaming RPC](https://grpc.io/docs/guides/concepts.html#bidirectional-streaming-rpc)
14
15 And concept of [metadata](https://grpc.io/docs/guides/concepts.html#metadata).
16
17 ## Constructing metadata
18
19 A metadata can be created using package [metadata](https://godoc.org/google.golang.org/grpc/metadata).
20 The type MD is actually a map from string to a list of strings:
21
22 ```go
23 type MD map[string][]string
24 ```
25
26 Metadata can be read like a normal map.
27 Note that the value type of this map is `[]string`,
28 so that users can attach multiple values using a single key.
29
30 ### Creating a new metadata
31
32 A metadata can be created from a `map[string]string` using function `New`:
33
34 ```go
35 md := metadata.New(map[string]string{"key1": "val1", "key2": "val2"})
36 ```
37
38 Another way is to use `Pairs`.
39 Values with the same key will be merged into a list:
40
41 ```go
42 md := metadata.Pairs(
43     "key1", "val1",
44     "key1", "val1-2", // "key1" will have map value []string{"val1", "val1-2"}
45     "key2", "val2",
46 )
47 ```
48
49 __Note:__ all the keys will be automatically converted to lowercase,
50 so "key1" and "kEy1" will be the same key and their values will be merged into the same list.
51 This happens for both `New` and `Pairs`.
52
53 ### Storing binary data in metadata
54
55 In metadata, keys are always strings. But values can be strings or binary data.
56 To store binary data value in metadata, simply add "-bin" suffix to the key.
57 The values with "-bin" suffixed keys will be encoded when creating the metadata:
58
59 ```go
60 md := metadata.Pairs(
61     "key", "string value",
62     "key-bin", string([]byte{96, 102}), // this binary data will be encoded (base64) before sending
63                                         // and will be decoded after being transferred.
64 )
65 ```
66
67 ## Retrieving metadata from context
68
69 Metadata can be retrieved from context using `FromIncomingContext`:
70
71 ```go
72 func (s *server) SomeRPC(ctx context.Context, in *pb.SomeRequest) (*pb.SomeResponse, err) {
73     md, ok := metadata.FromIncomingContext(ctx)
74     // do something with metadata
75 }
76 ```
77
78 ## Sending and receiving metadata - client side
79
80 [//]: # "TODO: uncomment next line after example source added"
81 [//]: # "Real metadata sending and receiving examples are available [here](TODO:example_dir)."
82
83 ### Sending metadata
84
85 To send metadata to server, the client can wrap the metadata into a context using `NewOutgoingContext`, and make the RPC with this context:
86
87 ```go
88 md := metadata.Pairs("key", "val")
89
90 // create a new context with this metadata
91 ctx := metadata.NewOutgoingContext(context.Background(), md)
92
93 // make unary RPC
94 response, err := client.SomeRPC(ctx, someRequest)
95
96 // or make streaming RPC
97 stream, err := client.SomeStreamingRPC(ctx)
98 ```
99
100 To read this back from the context on the client (e.g. in an interceptor) before the RPC is sent, use `FromOutgoingContext`.
101
102 ### Receiving metadata
103
104 Metadata that a client can receive includes header and trailer.
105
106 #### Unary call
107
108 Header and trailer sent along with a unary call can be retrieved using function [Header](https://godoc.org/google.golang.org/grpc#Header) and [Trailer](https://godoc.org/google.golang.org/grpc#Trailer) in [CallOption](https://godoc.org/google.golang.org/grpc#CallOption):
109
110 ```go
111 var header, trailer metadata.MD // variable to store header and trailer
112 r, err := client.SomeRPC(
113     ctx,
114     someRequest,
115     grpc.Header(&header),    // will retrieve header
116     grpc.Trailer(&trailer),  // will retrieve trailer
117 )
118
119 // do something with header and trailer
120 ```
121
122 #### Streaming call
123
124 For streaming calls including:
125
126 - Server streaming RPC
127 - Client streaming RPC
128 - Bidirectional streaming RPC
129
130 Header and trailer can be retrieved from the returned stream using function `Header` and `Trailer` in interface [ClientStream](https://godoc.org/google.golang.org/grpc#ClientStream):
131
132 ```go
133 stream, err := client.SomeStreamingRPC(ctx)
134
135 // retrieve header
136 header, err := stream.Header()
137
138 // retrieve trailer
139 trailer := stream.Trailer()
140
141 ```
142
143 ## Sending and receiving metadata - server side
144
145 [//]: # "TODO: uncomment next line after example source added"
146 [//]: # "Real metadata sending and receiving examples are available [here](TODO:example_dir)."
147
148 ### Receiving metadata
149
150 To read metadata sent by the client, the server needs to retrieve it from RPC context.
151 If it is a unary call, the RPC handler's context can be used.
152 For streaming calls, the server needs to get context from the stream.
153
154 #### Unary call
155
156 ```go
157 func (s *server) SomeRPC(ctx context.Context, in *pb.someRequest) (*pb.someResponse, error) {
158     md, ok := metadata.FromIncomingContext(ctx)
159     // do something with metadata
160 }
161 ```
162
163 #### Streaming call
164
165 ```go
166 func (s *server) SomeStreamingRPC(stream pb.Service_SomeStreamingRPCServer) error {
167     md, ok := metadata.FromIncomingContext(stream.Context()) // get context from stream
168     // do something with metadata
169 }
170 ```
171
172 ### Sending metadata
173
174 #### Unary call
175
176 To send header and trailer to client in unary call, the server can call [SendHeader](https://godoc.org/google.golang.org/grpc#SendHeader) and [SetTrailer](https://godoc.org/google.golang.org/grpc#SetTrailer) functions in module [grpc](https://godoc.org/google.golang.org/grpc).
177 These two functions take a context as the first parameter.
178 It should be the RPC handler's context or one derived from it:
179
180 ```go
181 func (s *server) SomeRPC(ctx context.Context, in *pb.someRequest) (*pb.someResponse, error) {
182     // create and send header
183     header := metadata.Pairs("header-key", "val")
184     grpc.SendHeader(ctx, header)
185     // create and set trailer
186     trailer := metadata.Pairs("trailer-key", "val")
187     grpc.SetTrailer(ctx, trailer)
188 }
189 ```
190
191 #### Streaming call
192
193 For streaming calls, header and trailer can be sent using function `SendHeader` and `SetTrailer` in interface [ServerStream](https://godoc.org/google.golang.org/grpc#ServerStream):
194
195 ```go
196 func (s *server) SomeStreamingRPC(stream pb.Service_SomeStreamingRPCServer) error {
197     // create and send header
198     header := metadata.Pairs("header-key", "val")
199     stream.SendHeader(header)
200     // create and set trailer
201     trailer := metadata.Pairs("trailer-key", "val")
202     stream.SetTrailer(trailer)
203 }
204 ```