Go语言中如何在Unary RPC处理函数内设置响应头(含缓存控制)
Setting Response Headers (Including Cache Control) in Go gRPC Unary Handlers
Got it, I've run into this exact issue before when trying to set cache headers in unary gRPC handlers. The key insight here is that even though unary RPC method signatures don't include a grpc.ServerStream (unlike streaming RPCs), you can still manipulate response headers using gRPC's context-based helper functions.
How It Works
gRPC embeds all necessary RPC context into the context.Context passed to your unary handler. You can use two core functions from the google.golang.org/grpc package to manage headers:
grpc.SendHeader(ctx, metadata): Sends initial response headers to the client (must be called before returning the response message).grpc.SetTrailer(ctx, metadata): Sets trailing metadata (can be called before or after sending the response).
Step-by-Step Example
First, make sure you import the required packages:
import ( "context" "google.golang.org/grpc" "google.golang.org/grpc/metadata" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" )
Then, in your unary handler, create and send the cache control headers:
func (s *yourServer) GetProduct(ctx context.Context, req *GetProductRequest) (*GetProductResponse, error) { // 1. Build your cache control (and other) headers as gRPC metadata responseHeaders := metadata.Pairs( "cache-control", "public, max-age=3600", // Standard cache control header "x-custom-cache-tag", "product-data", // Optional custom header ) // 2. Send the headers to the client if err := grpc.SendHeader(ctx, responseHeaders); err != nil { return nil, status.Errorf( codes.Internal, "failed to send response headers: %v", err, ) } // 3. Proceed with your normal request logic product, err := s.fetchProductFromDB(req.ProductID) if err != nil { return nil, status.Errorf(codes.NotFound, "product not found: %v", err) } // Optional: Set trailing metadata if needed (e.g., cache status) trailingMetadata := metadata.Pairs("x-cache-status", "hit") grpc.SetTrailer(ctx, trailingMetadata) return &GetProductResponse{Product: product}, nil }
Key Notes
- Timing Matters:
grpc.SendHeadermust be called before you return the response message. Once the response is sent, you can't modify the initial headers. - Header Naming: gRPC follows HTTP/2 conventions, so header keys are typically lowercase. While gRPC will normalize mixed-case keys, using lowercase avoids unexpected behavior.
- Client Side: If you're using a gRPC client, you can capture these headers using
grpc.Header()when making the call:var header metadata.MD resp, err := client.GetProduct( ctx, &GetProductRequest{ProductID: 123}, grpc.Header(&header), ) // Access headers via header.Get("cache-control") - gRPC-Gateway: If you're using gRPC-Gateway to expose your RPC as HTTP endpoints, these headers will automatically be passed through to the HTTP response, making your cache control rules work for HTTP clients too.
内容的提问来源于stack exchange,提问作者thurt
相关产品推荐
相关产品推荐

