登录
首页 >  Golang >  Go问答

grpc-gateway:如何处理非JSON格式的请求体?

来源:stackoverflow

时间:2024-02-21 08:45:24 370浏览 收藏

小伙伴们有没有觉得学习Golang很有意思?有意思就对了!今天就给大家带来《grpc-gateway:如何处理非JSON格式的请求体?》,以下内容将会涉及到,若是在学习中对其中部分知识点有疑问,或许看了本文就能帮到你!

问题内容

Grpc-gateway 提供了使用 google.api.HttpBody 自定义响应正文的解决方案(非 json 内容类型,如 text/plainapplication/xml 等),但是,此原始消息无法处理请求正文。


正确答案


受到 johanbrandhorst' comment 的启发,我想出了一个带有自定义封送拆收器的解决方案。我实现了 runtime.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")
    })
}

启动 grpc-gateway

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)
}

然后,对于所有内容类型指定为“application/xml”的请求,grpc-gateway 会将 xml 正文数据分配给 google.api.HttpBody.Data。并且,对于非 json 响应,grpc-gateway 会将 google.api.HttpBody.Data 分配给响应正文。

到这里,我们也就讲完了《grpc-gateway:如何处理非JSON格式的请求体?》的内容了。个人认为,基础知识的学习和巩固,是为了更好的将其运用到项目中,欢迎关注golang学习网公众号,带你了解更多关于的知识点!

声明:本文转载于:stackoverflow 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>