go : gin http2 push资源

背景:
使用gin 框架,http2 push资源到server
知识点:
http2 server push
HTTP/2旨在解决HTTP/1.x的许多缺陷。现代web页面使用许多资源:HTML、样式表、脚本、图像等等。在HTTP/1.x中,必须显式地请求这些资源中的每一个。这可能是一个缓慢的过程。浏览器从获取HTML开始,然后在解析和计算页面时逐步了解更多资源。由于服务器必须等待浏览器发出每个请求,因此网络通常处于空闲状态且未充分利用。

为了提高延迟,HTTP/2引入了服务器推送,它允许服务器在显式请求资源之前将资源推送到浏览器。服务器通常知道页面将需要的许多额外资源,并且可以在响应初始请求时开始推送这些资源。这允许服务器充分利用空闲的网络并提高页面加载时间。
在这里插入图片描述
在协议层,HTTP/2服务器推送由push-PROMISE帧驱动。PUSH_PROMISE描述服务器预测浏览器将在不久的将来发出的请求。一旦浏览器收到推送承诺,它就知道服务器将交付资源。如果浏览器稍后发现它需要此资源,它将等待推送完成,而不是发送新请求。这减少了浏览器在网络上等待的时间。

server push 在net/http 包里面实现
Go1.8引入了对从http.Server推送响应的支持。如果正在运行的服务器是HTTP/2服务器,并且传入连接使用HTTP/2,则此功能可用。在任何HTTP处理程序中,都可以通过检查HTTP.ResponseWriter是否实现了新的HTTP.Pusher接口来断言它是否支持服务器推送。

例如,如果服务器知道需要app.js来呈现页面,则处理程序可以在http.Pusher可用时启动推送:

http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        if pusher, ok := w.(http.Pusher); ok {
            // Push is supported.
            if err := pusher.Push("/app.js", nil); err != nil {
                log.Printf("Failed to push: %v", err)
            }
        }
        // ...
    })

Push调用为/app.js创建一个合成请求,将该请求合成为Push-PROMISE框架,然后将合成请求转发给服务器的请求处理程序,后者将生成Push响应。Push的第二个参数指定了Push-PROMISE中要包含的附加头。例如,如果对/app.js的响应在接受编码上有所不同,那么PUSH_PROMISE应该包含一个接受编码值:

http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        if pusher, ok := w.(http.Pusher); ok {
            // Push is supported.
            options := &http.PushOptions{
                Header: http.Header{
                    "Accept-Encoding": r.Header["Accept-Encoding"],
                },
            }
            if err := pusher.Push("/app.js", options); err != nil {
                log.Printf("Failed to push: %v", err)
            }
        }
        // ...
    })

关于http2 push 参考 http2 push
实验代码:

package main

import (
	"html/template"
	"log"

	"github.com/gin-gonic/gin"
)

var html = template.Must(template.New("https").Parse(`
<html>
<head>
  <title>Https Test</title>
  <script src="/assets/app.js"></script>
</head>
<body>
  <h1 style="color:red;">Welcome, Ginner!</h1>
</body>
</html>
`))

func main() {
	r := gin.Default()
	r.Static("/assets", "./assets")
	r.SetHTMLTemplate(html)

	r.GET("/", func(c *gin.Context) {
		if pusher := c.Writer.Pusher(); pusher != nil {
			// use pusher.Push() to do server push
			if err := pusher.Push("/assets/app.js", nil); err != nil {
				log.Printf("Failed to push: %v", err)
			}
		}
		c.HTML(200, "https", gin.H{
			"status": "success",
		})
	})

	// Listen and Server in https://127.0.0.1:8080
	r.RunTLS(":8080", "./testdata/server.pem", "./testdata/server.key")
}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值