.NET Core中REST服务调用gRPC服务时自定义请求头如何透传
.NET Core gRPC跨服务请求头透传实现方案
你之前对Interceptor的认知存在偏差,.NET gRPC的客户端拦截器完全可以操作Metadata集合,只需要按以下步骤实现即可:
全局透传方案(推荐)
适合需要统一透传所有请求头的场景,无需每次调用手动处理:
- 第一步:在服务A中注册HttpContext访问器,用于获取用户传入的REST请求头
// Program.cs builder.Services.AddHttpContextAccessor();
- 第二步:自定义gRPC客户端拦截器,继承
Interceptor类,从HttpContext中提取需要透传的头注入到gRPC请求Metadata中
public class HeaderPropagationInterceptor : Interceptor { private readonly IHttpContextAccessor _httpContextAccessor; // 配置需要透传的请求头列表,可根据业务调整 private readonly List<string> _allowedHeaders = new() { "Authorization", "X-Trace-Id", "X-User-Id" }; public HeaderPropagationInterceptor(IHttpContextAccessor httpContextAccessor) { _httpContextAccessor = httpContextAccessor; } // 重写一元调用拦截逻辑,流式调用按需重写对应方法即可 public override AsyncUnaryCall<TResponse> AsyncUnaryCall<TRequest, TResponse>( TRequest request, ClientInterceptorContext<TRequest, TResponse> context, AsyncUnaryCallContinuation<TRequest, TResponse> continuation) { var httpContext = _httpContextAccessor.HttpContext; if (httpContext != null) { var headers = context.Options.Headers ?? new Metadata(); foreach (var headerName in _allowedHeaders) { if (httpContext.Request.Headers.TryGetValue(headerName, out var headerValue)) { // 重复头处理逻辑:先移除旧值再添加新值,也可根据需求改为跳过 headers.Remove(headerName); headers.Add(headerName, headerValue.ToString()); } } // 更新上下文的请求头配置 context = new ClientInterceptorContext<TRequest, TResponse>( context.Method, context.Host, context.Options.WithHeaders(headers)); } return continuation(request, context); } }
- 第三步:注册gRPC客户端时绑定拦截器
// Program.cs builder.Services.AddGrpcClient<ServiceBGrpc.ServiceBGrpcClient>(options => { options.Address = new Uri("https://你的服务B访问地址"); }) .AddInterceptor<HeaderPropagationInterceptor>();
配置完成后,服务A中所有通过注入的gRPC客户端发起的调用,都会自动透传配置的请求头到服务B。
单次调用手动透传方案
适合仅部分接口需要透传头的场景:
直接在调用gRPC方法时手动构造Metadata传入即可:
var headers = new Metadata(); // 从当前HttpContext提取需要透传的头 if (_httpContextAccessor.HttpContext.Request.Headers.TryGetValue("Authorization", out var auth)) { headers.Add("Authorization", auth.ToString()); } // 调用gRPC方法时传入头 var response = await _serviceBClient.SomeMethodAsync(req, headers);
服务B侧获取透传的请求头
在服务B的gRPC接口实现中,直接从ServerCallContext中读取头即可:
public override Task<MethodResp> SomeMethod(MethodReq req, ServerCallContext context) { var authHeader = context.RequestHeaders.GetValue("Authorization"); // 业务逻辑处理 }
补充说明
你之前认为Interceptor没有暴露Metadata,是因为忽略了ClientInterceptorContext中Options属性携带的Headers就是Metadata集合,所有客户端拦截方法都会传入该上下文,支持读取和修改。
内容的提问来源于stack exchange,提问作者RagHaven
相关产品推荐
相关产品推荐

