如何使用Golang编写我的Web服务器以支持HTTP / 2服务器推送?

时间:2017-01-05 16:48:37

标签: go server http2

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

2 个答案:

答案 0 :(得分:5)

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并直接编写帧。

答案 1 :(得分:0)

如其他答案中所述,您可以使用Go 1.8功能(将编写器转换为http.Pusher,然后使用Push方法)。

需要注意的是:您必须直接从服务器提供HTTP2流量。

如果你是像NGINX这样的代理,那么这可能不起作用。如果您想考虑这种情况,可以使用Link标头来宣传要推送的网址。

// 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/