[prpc] Add support for outgoing metadata

Include outgoing metadata of the current context into request HTTP headers.
From doc.go:

- Any other headers MUST be added to metadata.MD in the context that is
  passed to the service method implementation.
  - If a header name has "-Bin" suffix, the server must treat it as
    base64-encoded and trim the suffix.

R=vadimsh@chromium.org

Bug: 843714
Change-Id: Ib55b736accb199a9b54ffacafea0aa00c9985140
Reviewed-on: https://chromium-review.googlesource.com/c/1329989
Auto-Submit: Nodir Turakulov <nodir@chromium.org>
Commit-Queue: Vadim Shtayura <vadimsh@chromium.org>
Reviewed-by: Vadim Shtayura <vadimsh@chromium.org>
diff --git a/grpc/prpc/client.go b/grpc/prpc/client.go
index e5b2268..2167b3d 100644
--- a/grpc/prpc/client.go
+++ b/grpc/prpc/client.go
@@ -153,7 +153,8 @@
 		return nil, err
 	}
 
-	req := prepareRequest(c.Host, serviceName, methodName, len(in), inf, outf, options)
+	md, _ := metadata.FromOutgoingContext(ctx)
+	req := prepareRequest(c.Host, serviceName, methodName, md, len(in), inf, outf, options)
 	ctx = logging.SetFields(ctx, logging.Fields{
 		"host":    c.Host,
 		"service": serviceName,
@@ -352,7 +353,7 @@
 
 // prepareRequest creates an HTTP request for an RPC,
 // except it does not set the request body.
-func prepareRequest(host, serviceName, methodName string, contentLength int, inf, outf Format, options *Options) *http.Request {
+func prepareRequest(host, serviceName, methodName string, md metadata.MD, contentLength int, inf, outf Format, options *Options) *http.Request {
 	if host == "" {
 		panic("Host is not set")
 	}
@@ -363,7 +364,7 @@
 			Host:   host,
 			Path:   fmt.Sprintf("/prpc/%s/%s", serviceName, methodName),
 		},
-		Header: http.Header{},
+		Header: http.Header(md.Copy()),
 	}
 	if options.Insecure {
 		req.URL.Scheme = "http"
diff --git a/grpc/prpc/client_test.go b/grpc/prpc/client_test.go
index 9a79927..01bdb7f 100644
--- a/grpc/prpc/client_test.go
+++ b/grpc/prpc/client_test.go
@@ -179,6 +179,23 @@
 				So(log, shouldHaveMessagesLike, expectedCallLogEntry(client))
 			})
 
+			Convey("With outgoing metadata", func(c C) {
+				var receivedHeader http.Header
+				greeter := sayHello(c)
+				client, server := setUp(func(w http.ResponseWriter, r *http.Request) {
+					receivedHeader = r.Header
+					greeter(w, r)
+				})
+				defer server.Close()
+
+				ctx = metadata.NewOutgoingContext(ctx, metadata.Pairs("key", "value"))
+
+				err := client.Call(ctx, "prpc.Greeter", "SayHello", req, res)
+				So(err, ShouldBeNil)
+
+				So(receivedHeader.Get("key"), ShouldEqual, "value")
+			})
+
 			Convey("With a deadline <= now, does not execute.", func(c C) {
 				client, server := setUp(doPanicHandler)
 				defer server.Close()