如何在grpc-gateway的marshaller中获取请求上下文ctx?
grpc-gateway带上下文的自定义编解码解决方案
方案1:实现上下文感知的自定义Marshaler
grpc-gateway的runtime.Marshaler接口原生支持在Marshal和Unmarshal方法中接收context.Context参数,你可以直接基于这个接口实现自己的编解码器,对接你的MyMarshall和MyUnmarshall方法:
type CustomMarshaler struct { // 嵌入默认JSON编解码器,复用基础JSON处理逻辑 *runtime.JSONPb } // 重写Marshal方法,传入上下文调用自定义逻辑 func (m *CustomMarshaler) Marshal(ctx context.Context, v interface{}) ([]byte, error) { // 从ctx中提取所需上下文信息(如用户权限) permissions, ok := ctx.Value("user_permissions").([]string) if !ok { return nil, errors.New("无法从上下文获取用户权限") } // 调用你的自定义Marshal函数 return MyMarshall(ctx, v, permissions) } // 重写Unmarshal方法,传入上下文调用自定义逻辑 func (m *CustomMarshaler) Unmarshal(ctx context.Context, data []byte, v interface{}) error { permissions, ok := ctx.Value("user_permissions").([]string) if !ok { return errors.New("无法从上下文获取用户权限") } // 调用你的自定义Unmarshal函数 return MyUnmarshall(ctx, data, v, permissions) }
注册该编解码器到网关:
mux := runtime.NewServeMux( runtime.WithMarshalerOption(runtime.MIMEWildcard, &CustomMarshaler{ JSONPb: &runtime.JSONPb{ MarshalOptions: jsonpb.MarshalOptions{Indent: " "}, UnmarshalOptions: jsonpb.UnmarshalOptions{}, }, }), )
方案2:通过HTTP拦截器注入上下文信息
如果上下文信息(如用户权限)需要从HTTP请求中提取,先通过拦截器将信息注入到context.Context,再在自定义编解码器中读取:
// 自定义拦截器:从请求中提取用户权限并存入上下文 func injectPermissions(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // 从请求头、token等位置提取用户权限 permissions := extractPermissions(r) // 将权限存入请求上下文 ctx := context.WithValue(r.Context(), "user_permissions", permissions) // 传递带权限的上下文到后续流程 next.ServeHTTP(w, r.WithContext(ctx)) }) } // 将拦截器绑定到网关路由 http.Handle("/", injectPermissions(mux))
关键注意事项
- 确保上下文信息在请求流程的早期被注入,编解码器才能正确读取。
- 若需处理流式请求,需额外实现
runtime.StreamMarshaler接口,该接口同样支持接收context.Context参数。
内容的提问来源于stack exchange,提问作者Boolangery
相关产品推荐
相关产品推荐

