首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >grpc-网关:如何设置每个请求允许的内容类型

grpc-网关:如何设置每个请求允许的内容类型
EN

Stack Overflow用户
提问于 2021-04-08 12:48:45
回答 1查看 1.8K关注 0票数 1

我在同一个go应用程序中使用grpc-gateway,代理将HTTP转换为GRPC。据我所见,默认情况下,grpc-gateway为所有rpcs设置应用程序application/json格式,包括流。

所以,我的任务是:

  1. 传入的HTTP请求必须始终是Content-type: application/json,否则请求将被拒绝,并根据RFC发送406。
  2. 传入的HTTP请求可以为一元RPC设置Accept: application/x-ndjson,为服务器流设置Accept: applcation/x-ndjson报头。如果条件不符合406,则应退还。
  3. 传出HTTP请求必须为简单的一元RPC设置Content-type: applicaiton/json,为服务器流设置Content-type: application/x-ndjson

因此,grpc-gateway建议只为application/x-ndjson设置自定义封送拆收器,这实际上与默认的设置相同,因此只使用覆盖的ContentType方法。这种方法不允许我为每个方法调用设置封送处理程序,也不允许我拒绝每个请求不受支持的内容类型。

我如何仍然使用grpc-gateway来实现这一点?还是我应该考虑手动实现http转换?

EN

回答 1

Stack Overflow用户

发布于 2021-04-09 14:24:29

我建议您不要使用gRPC网关或任何其他工具将gRPC转换为HTTP。您正在为您的应用程序添加不必要的复杂性。

如果您有一个gRPC服务,但是由于任何原因,您的客户端不能调用gRPC,您需要通过一个普通的HTTP选项提供服务.那是你的案子吗?

如果是这样的话,正确的方法是提供HTTP服务,然后从它调用您的gRPC服务。

HTTP比REST简单得多,您不需要任何工具。

我在GOlang 这里中实现了这个精确的案例

代码语言:javascript
复制
    // Creates a new book.
func (h BookStoreService) CreateBook(w http.ResponseWriter, r *http.Request) {
    request := &bookv1.CreateBookRequest{}
    proxy := httputil.GetProxy(w, r, request)
    proxy.SetServiceRequest(func(request proto.Message) (proto.Message, error) {
        return h.client.CreateBook(r.Context(), request.(*bookv1.CreateBookRequest))
    })
    proxy.Call()
}

代理结构

代码语言:javascript
复制
func GetProxy(w http.ResponseWriter, r *http.Request, request proto.Message) *ServiceProxy {
    proxy := &ServiceProxy{}
    proxy.SetResponseWriter(w)
    proxy.SetSourceRequest(r)
    proxy.SetDestRequest(request)
    return proxy
}

type ServiceProxy struct {
    err            error
    serviceRequest func(request proto.Message) (proto.Message, error)
    writer         http.ResponseWriter
    destRequest    proto.Message
    sourceRequest  *http.Request
}

func (b *ServiceProxy) SetDestRequest(request proto.Message) {
    b.destRequest = request
}

func (b *ServiceProxy) SetSourceRequest(request *http.Request) {
    b.sourceRequest = request
}

func (b *ServiceProxy) SetServiceRequest(svcRequest func(request proto.Message) (proto.Message, error)) *ServiceProxy {
    b.serviceRequest = svcRequest
    return b
}

func (b *ServiceProxy) Call() {
    b.writer.Header().Set("Content-Type", "application/json; charset=utf-8")
    err := unmarshal(b.writer, b.sourceRequest, b.destRequest)
    if err != nil {
        return
    }
    resp, err := b.serviceRequest(b.destRequest)
    if err != nil {
        handleErrorResp(b.writer, err)
        return
    }
    b.writer.WriteHeader(http.StatusOK)
    json.NewEncoder(b.writer).Encode(resp)
}

func (b *ServiceProxy) SetResponseWriter(w http.ResponseWriter) {
    b.writer = w
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67004324

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档