【问题标题】:ETags and 304 Not Modified response in grpc REST gatewaygrpc REST 网关中的 ETags 和 304 Not Modified 响应
【发布时间】:2017-10-06 14:34:23
【问题描述】:

我正在使用 Github 的 grpc-gateway 项目从 gRPC 规范自动生成 REST API。在这个 REST API 中,我想支持 ETag 标头和 304 Not Modified 响应。

据我了解,通常您会在 gRPC 服务器中创建一个带有特定状态代码的响应,然后该状态代码将被 grpc-gateway 转换为 HTTP 状态代码。但是,由于标准 gRPC 并不真正支持缓存概念,因此没有映射到 HTTP 304 状态代码的 gRPC 状态代码。

使用 grpc-gateway,似乎可以在 gRPC 状态码为错误码时自定义 HTTP 状态码(覆盖 runtime.HTTPError 函数)。但是,我还没有找到任何方法可以在 gRPC 响应代码正常的情况下自定义 HTTP 响应代码。

那么,有没有推荐的方法来实现这一点?

【问题讨论】:

  • 我也对此感兴趣。以下是我通过 github repo 发现的一些相关问题:github.com/grpc-ecosystem/grpc-gateway/issues/240 & github.com/grpc-ecosystem/grpc-gateway/issues/517
  • 相关google群组讨论:groups.google.com/forum/#!topic/grpc-io/1TJspS7QRwUquoteI would say that this [caching] isn't really something we would like to introduce in the core of grpc. It is indeed left as an exercise to the reader in the sense that it is rather something that you would implement in your messages. Not all kinds of rpc would find that feature relevant, so let's not make all of them pay its cost on the critical path. Authentication on the other hand is on the channel itself, and the presence of the code won't impact non-authenticated channels.

标签: rest go grpc


【解决方案1】:

这是一个使用自定义转发器实现基本 etag 和 304 响应的示例。

您可以参考这些directions进行设置,然后按照以下方式实现方法:

func forwardGetPost(ctx context.Context, mux *runtime.ServeMux, marshaler runtime.Marshaler, w http.ResponseWriter, req *http.Request, resp proto.Message, opts ...func(context.Context, http.ResponseWriter, proto.Message) error) {
    // add cache-control rules for this proxy endpoint
    w.Header().Add("Cache-Control", "max-age=60")

    // create an etag
    // (when the response represents some entity from the db it may have a last edited timestamp)
    p := resp.(*Post)
    etag := fmt.Sprintf("W/%q", p.GetLastEdited())
    w.Header().Add("ETag", etag)

    // check whether the request provides an etag
    inm := req.Header.Get("If-None-Match")
    if inm != "" {
        if inm == etag {
            w.WriteHeader(http.StatusNotModified)
        }
    }
    runtime.ForwardResponseMessage(ctx, mux, marshaler, w, req, resp, opts...)
}

这不会阻止代理向 grpc 服务器发出请求,但会阻止在 etag 匹配时将这些字节发送回客户端。

【讨论】:

  • 您好,感谢您的回复!我猜您的建议适用于带有 If-None-Match 标头的 GET 请求。但是,它似乎确实要求实体中有一些属性可以充当 ETag(在您的示例中为“LastEdited”),但情况可能并非总是如此。一个相关的问题是如何处理带有“If-Match”标头的 POST/PUT 请求,其中 If-Match 标头需要以某种方式通过 gRPC 转发。
  • 是的,很好的观察结果,我也一直在尝试找出这些案例。关于 Etags,有些人会使用整个响应的 md5/sha1 哈希。因此,转发器不需要知道响应的类型或依赖任何响应字段来创建 Etag。权衡是创建散列需要更多的 CPU。
猜你喜欢
  • 2016-03-29
  • 1970-01-01
  • 1970-01-01
  • 2010-09-05
  • 2011-03-03
  • 2021-08-16
  • 2014-07-22
  • 2013-10-06
  • 2016-08-08
相关资源
最近更新 更多