Metadata Roundtrip
Client sends metadata, server reads it and sends response metadata back.
Client — cmd/client/main.go
import (
"context"
"fmt"
"google.golang.org/grpc"
"google.golang.org/grpc/metadata"
"shortener/pb"
)
func getWithMetadata(client pb.LinkServiceClient) {
ctx := metadata.AppendToOutgoingContext(context.Background(),
"authorization", "Bearer my-token",
"x-request-id", "req-12345",
)
var header, trailer metadata.MD
resp, err := client.GetLink(ctx, &pb.GetLinkRequest{ShortCode: "abc123"},
grpc.Header(&header),
grpc.Trailer(&trailer),
)
if err != nil {
fmt.Printf("error: %v\n", err)
return
}
fmt.Printf("link: %s\n", resp.GetLink().GetUrl())
fmt.Println("served by:", header.Get("x-served-by"))
fmt.Println("timing:", trailer.Get("x-duration"))
}Server — main.go
import (
"log"
"time"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/metadata"
"google.golang.org/grpc/status"
)
func (s *linkServer) GetLink(ctx context.Context, req *pb.GetLinkRequest) (*pb.GetLinkResponse, error) {
md, _ := metadata.FromIncomingContext(ctx)
reqID := ""
if vals := md.Get("x-request-id"); len(vals) > 0 {
reqID = vals[0]
}
log.Printf("request_id=%s", reqID)
grpc.SendHeader(ctx, metadata.Pairs("x-served-by", "node-1"))
start := time.Now()
s.mu.RLock()
link, ok := s.links[req.GetShortCode()]
s.mu.RUnlock()
if !ok {
return nil, status.Errorf(codes.NotFound, "link not found: %s", req.GetShortCode())
}
grpc.SetTrailer(ctx, metadata.Pairs("x-duration", time.Since(start).String()))
return &pb.GetLinkResponse{Link: link}, nil
}