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

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

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

那么,有没有推荐的方法可以做到这一点?

最佳答案

这是一个使用自定义转发器实现基本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服务器发出请求,但会阻止etags匹配时将这些字节发送回客户端。

关于rest - grpc REST网关中的ETag和304 Not Modified响应,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/46608167/

10-16 13:05