[英]Grpc-gateway: how to deal with non-json request body?
Grpc-gateway offers solutions for customizing response body using google.api.HttpBody
(non-json content type like text/plain
, application/xml
, etc), however, this proto message cannot deal with request body. Grpc-gateway 提供了使用
google.api.HttpBody
(非 json 内容类型,如text/plain
、 application/xml
等)自定义响应正文的解决方案,但是,此 proto 消息无法处理请求正文。
Inspired by johanbrandhorst' comment , I came up with a solution with a customized marshaler.受到johanbrandhorst 评论的启发,我想出了一个带有定制编组器的解决方案。 I implemented interfaces of runtime.marshaler to create my own marshaler.
我实现了runtime.marshaler的接口来创建我自己的 marshaler。
Custiomized marshaler自定义编组器
package marshaler
import (
"errors"
"io"
"io/ioutil"
"log"
"reflect"
"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
"google.golang.org/genproto/googleapis/api/httpbody"
)
type XMLMarshaler struct {
runtime.Marshaler
}
func (x XMLMarshaler) ContentType(_ interface{}) string {
return "application/xml"
}
func (x XMLMarshaler) Marshal(v interface{}) ([]byte, error) {
log.Println("xml marshal")
log.Printf("param: %+v", v)
// return xml.Marshal(v)
if httpBody, ok := v.(*httpbody.HttpBody); ok {
return httpBody.Data, nil
}
return x.Marshaler.Marshal(v)
}
func (x XMLMarshaler) NewDecoder(r io.Reader) runtime.Decoder {
log.Println("xml new decoder")
return runtime.DecoderFunc(func(p interface{}) error {
buffer, err := ioutil.ReadAll(r)
if err != nil {
return err
}
pType := reflect.TypeOf(p)
if pType.Kind() == reflect.Ptr {
v := reflect.Indirect(reflect.ValueOf(p))
if v.Kind() == reflect.String {
v.Set(reflect.ValueOf(string(buffer)))
return nil
}
}
return errors.New("value type error")
})
}
starting grpc-gateway启动 grpc 网关
func run() error {
ctx := context.Background()
ctx, cancel := context.WithCancel(ctx)
defer cancel()
// Register gRPC server endpoint
// Note: Make sure the gRPC server is running properly and accessible
mux := runtime.NewServeMux(
runtime.WithMarshalerOption("application/xml", marshaler.XMLMarshaler{}),
)
opts := []grpc.DialOption{grpc.WithTransportCredentials(insecure.NewCredentials())}
err := gw.RegisterBotServiceHandlerFromEndpoint(ctx, mux, *grpcServerEndpoint, opts)
if err != nil {
return err
}
// Start HTTP server (and proxy calls to gRPC server endpoint)
return http.ListenAndServe(":8080", mux)
}
Then, for all requests with content type specified as "application/xml", grpc-gateway
will assign the XML body data to google.api.HttpBody.Data .然后,对于内容类型指定为“application/xml”的所有请求,
grpc-gateway
会将 XML 正文数据分配给google.api.HttpBody.Data 。 And, for non-json responses, grpc-gateway
will assign google.api.HttpBody.Data to response body.而且,对于非 json 响应,
grpc-gateway
会将google.api.HttpBody.Data分配给响应正文。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.