grpc/server/responseheader/responseheader.go (30 lines of code) (raw):
package responseheader
import (
"context"
"google.golang.org/grpc"
"google.golang.org/grpc/metadata"
)
// UnaryServerInterceptor returns a server interceptor
// that copies selected request metadata into response metadata.
func UnaryServerInterceptor(metadataToHeader map[string]string) grpc.UnaryServerInterceptor {
return func(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (any, error) {
if err := copyMetadata(ctx, metadataToHeader); err != nil {
return nil, err
}
return handler(ctx, req)
}
}
func copyMetadata(ctx context.Context, metadataToHeader map[string]string) error {
md, ok := metadata.FromIncomingContext(ctx)
if !ok {
return nil
}
// Filter and set the allowed metadata as response headers
filteredMD := metadata.New(nil)
for key := range metadataToHeader {
if values, exists := md[key]; exists {
filteredMD.Set(key, values...)
}
}
// append filteredMD to any existing headers, does not replace the entire header metadata
// if setHeader called multiple times, all the provided metadata will be merged
if err := grpc.SetHeader(ctx, filteredMD); err != nil {
return err
}
return nil
}