来自公众号:新世界杂货铺
在HTTP1.x中,访问一个页面,浏览器首先获取HTML资源,而后在解析页面时增量地获取其余资源,服务器必须等待浏览器发出请求后才下发页面内资源。而服务器其实是知道页面内资源有哪些的,若是服务器可以在浏览器显式请求资源以前就将资源推送到浏览器,页面加载速度将会大大提示,这也是本篇的主旨。javascript
本篇主要分为两个部分,第一部分是用go实现的服务器推送例子,第二部分是自签名证书。为何会有自签名证书,这里笔者先卖个关子,继续阅读后文将会守得云开见月明。css
目前仅有HTTP2支持服务器推送,HTTP1.x不支持服务器推送,那咱们在代码中应该如何判断当前服务器是否支持推送?html
在Go中,咱们经过判断http.ResponseWriter
是否实现了http.Pusher
接口就能够知道当前服务器是否支持推送。前端
下面为笔者写下的第一个服务器推送例子:java
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { if r.URL.Path != "/" { http.NotFound(w, r) return } pusher, ok := w.(http.Pusher) if ok { // 主动推送服务资源 if err := pusher.Push("/static/app.js", nil); err != nil { log.Printf("Failed to push: %v", err) } if err := pusher.Push("/static/style.css", nil); err != nil { log.Printf("Failed to push: %v", err) } } // 下发浏览器首屏资源 fmt.Fprintf(w, `<html> <head> <title>新世界杂货铺</title> <link rel="stylesheet" href="/static/style.css""> </head> <body> <div>Hello 新世界杂货铺</div> <div id="content"></div> <script src="/static/app.js"></script> </body> </html>`) }) http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("static")))) http.ListenAndServe(":8080", nil)
上述代码中app.js内容以下:git
document.getElementById("content").innerHTML = '"新世界杂货铺" from js'
运行上述代码后,在浏览器中访问http://localhost:8080/
获得以下结果:github
咱们看上图中标红部分发现js资源和样式资源并非服务器推送下发的,并且使用的是HTTP1.1,结合笔者前面的文章知道Go是支持HTTP2的且HTTP2须要使用SSL/TLS即HTTPS。所以,笔者修改监听代码以下:golang
http.ListenAndServeTLS(":8080", "ca.crt", "ca.key", nil)
再次运行上述代码,并在浏览器中访问https://localhost:8080/
获得以下结果:shell
咱们看图中红色部分知本次请求使用了HTTP2协议,而且静态资源由服务器推送。浏览器
上述代码中ca.crt
和ca.key
分别为自签名证书以及私钥,该证书及私钥已上传至笔者的github,github连接见文末。
注:笔者生成证书环境为macOS
笔者生成自签名证书时,先祭出搜索大法,而后使用网上的命令生成证书,最后证书是生成了,可是运行上述例子后在浏览器中的访问结果却不尽人意。
首先执行下述命令生成证书:
// 生成私钥 openssl genrsa -out old.key 2048 // 生成证书签名请求,此时须要填写一些证书信息 openssl req -new -key old.key -out old.csr // 签发证书 openssl x509 -req -days 365 -in old.csr -signkey old.key -out old.crt
修改例子中的证书和私钥为old.crt
和old.key
,最后在Chrome浏览器中访问结果以下:
上述页面给了不安全提示却没法继续不安全访问(Safari浏览器能够进行不安全地访问),做为一个轻微强迫症患者,笔者的心里有一丝丝难受。
因而笔者翻了openssl官网,最后对生成自签名证书的命令作了改进。
首先在执行命令的目录建立一个ca.cnf
(能够随意命名),并在该文件中写入以下内容:
# 更多x509v3_config见https://www.openssl.org/docs/man1.1.1/man5/x509v3_config.html [ ca_conf ] extendedKeyUsage = serverAuth # 可以继续进行不安全地访问的关键 basicConstraints = CA:FALSE
改进后的签名命令以下:
// 生成私钥 openssl genrsa -out ca.key 2048 // 生成证书签名请求,此时须要填写一些证书信息 openssl req -new -key ca.key -out ca.csr // 签发证书 openssl x509 -req -sha256 -extfile ca.cnf -extensions ca_conf -days 365 -in ca.csr -signkey ca.key -out ca.crt
此证书即为前面例子所使用的证书,而且第一次在浏览器中访问会有以下提示:
点击图中红框部分便可正常访问页面。
完成上面的例子以后,笔者特地去观察了百度、淘宝和谷歌的首页发现你们均已开始使用HTTP2,可是好像尚未公司使用服务器推送。
所以笔者下面的总结全凭我的经验猜想:
最后,衷心但愿本文可以对各位读者有必定的帮助。
参考
https://blog.golang.org/h2push
https://blog.csdn.net/qq_4187...
注:
- 写本文时, 笔者所用go版本为: go1.15.2
- 文章中所用完整例子:https://github.com/Isites/go-...