使用gRPC-Gateway时拦截器获取错误User-Agent问题排查
gRPC-Gateway拦截器获取到错误的User-Agent(grpc-go/xxx)而非原始请求值
问题根源
你遇到的问题本质是gRPC-Gateway作为HTTP转gRPC的网关客户端时,会自动添加自身的user-agent元数据(值为grpc-go/xxx),而你配置的HeaderMatcher将原始HTTP请求的User-Agent映射为大写的User-Agent元数据key,两者在metadata中并存。
由于gRPC的metadata.Get()方法会自动将传入的key转为小写后查找,所以你在后端拦截器中调用md.Get("User-Agent")时,实际匹配到的是网关客户端自动添加的小写user-agent键对应的值,而非原始HTTP请求的User-Agent。
解决方案
修改你的customHeaderMatcher函数,将HTTP请求的User-Agent头映射为小写的user-agent元数据key。这样gRPC客户端发现该key已存在时,就不会再自动添加自身的User-Agent值,后端就能拿到原始请求的User-Agent。
修改后的代码:
func customHeaderMatcher(key string) (string, bool) { switch key { case "Cookie": logger.Info(key) return key, true case "User-Agent": logger.Info(key) return "user-agent", true // 改为小写key,覆盖网关客户端自动添加的元数据 default: return runtime.DefaultHeaderMatcher(key) } }
额外验证建议
可以在后端拦截器中打印完整的metadata,确认元数据键值对是否符合预期:
logger.Infof("完整metadata: %v", md)
如果需要确认网关是否正确接收到原始HTTP请求的User-Agent,可以在gRPC-Gateway的ServeMux前添加一个HTTP中间件,打印请求头:
http.Handle("/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { logger.Infof("原始HTTP请求User-Agent: %s", r.Header.Get("User-Agent")) s.mux.ServeHTTP(w, r) }))
内容的提问来源于stack exchange,提问作者Cross
相关产品推荐
相关产品推荐

