【问题标题】:How to Make My Web Server written in Golang to support HTTP/2 Server Push?如何让我的用 Golang 编写的 Web 服务器支持 HTTP/2 服务器推送?
【发布时间】:2017-05-20 07:28:35
【问题描述】:

我的 Web 服务器是用 Golang 编码的,并且支持 HTTPS。我希望利用 Web 服务器中的 HTTP/2 服务器推送功能。以下链接解释了如何将 HTTP 服务器转换为支持 HTTP/2:- https://www.ianlewis.org/en/http2-and-go
但是,目前尚不清楚如何在 Golang 中实现服务器推送通知。
- 我应该如何添加服务器推送功能?
- 我如何控制或管理要推送的文档和文件?

【问题讨论】:

  • 信息不多,但关于主题:stackoverflow.com/questions/37872924/…
  • 请注意,“推送通知”与“服务器推送”不同。顺便说一句,我在 Google AppEngine 中运行 Go 的经验是,我需要设置如下的 http 标头来指示要推送的文件:link:/bg.jpg>;相对=预载; as=图像,;相对=预载; as=脚本

标签: go server http2


【解决方案1】:

Go 1.7 及更早版本不支持标准库中的 HTTP/2 服务器推送。即将发布的 1.8 版本中将添加对服务器推送的支持(请参阅release notes,预计发布时间为 2 月)。

在 Go 1.8 中,您可以使用新的 http.Pusher 接口,该接口由 net/http 的默认 ResponseWriter 实现。如果服务器推送不支持 (HTTP/1) 或不允许(客户端已禁用服务器推送),Pushers Push 方法返回 ErrNotSupported。

例子:

package main                                                                              

import (
    "io"
    "log"
    "net/http"
)

func main() {
    http.HandleFunc("/pushed", func(w http.ResponseWriter, r *http.Request) {
        io.WriteString(w, "hello server push")
    })

    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        if pusher, ok := w.(http.Pusher); ok {
            if err := pusher.Push("/pushed", nil); err != nil {
                log.Println("push failed")
            }
        }

        io.WriteString(w, "hello world")
    })

    http.ListenAndServeTLS(":443", "server.crt", "server.key", nil)
}

如果你想在 Go 1.7 或更早版本中使用服务器推送,可以使用 golang.org/x/net/http2 并直接写入帧。

【讨论】:

  • Go 1.8 也将于 2 月发布。
【解决方案2】:

正如其他答案中提到的,您可以使用 Go 1.8 功能(将作者转换为 http.Pusher,然后使用 Push 方法)。

附带一个警告:您必须直接从您的服务器提供 HTTP2 流量。

如果您使用 NGINX 之类的代理,这可能不起作用。如果您想考虑这种情况,您可以使用Link 标头来通告要推送的 URL。

// In the case of HTTP1.1 we make use of the `Link` header
// to indicate that the client (in our case, NGINX) should
// retrieve a certain URL.
//
// See more at https://www.w3.org/TR/preload/#server-push-http-2.
func handleIndex(w http.ResponseWriter, r *http.Request) {
  var err error

  if *http2 {
    pusher, ok := w.(http.Pusher)
    if ok {
      must(pusher.Push("/image.svg", nil))
    }
  } else {
    // This ends up taking the effect of a server push
    // when interacting directly with NGINX.
    w.Header().Add("Link", 
      "</image.svg>; rel=preload; as=image")
  }

  w.Header().Add("Content-Type", "text/html")
  _, err = w.Write(assets.Index)
  must(err)
}

ps.:如果您有兴趣,我在这里https://ops.tips/blog/nginx-http2-server-push/ 写了更多关于此的内容。

【讨论】:

    猜你喜欢
    • 2017-03-04
    • 2015-04-15
    • 2016-02-05
    • 2017-09-06
    • 2016-06-14
    • 2013-01-14
    • 2015-06-03
    • 2018-02-25
    • 2016-06-20
    相关资源
    最近更新 更多