來自公衆號:新世界雜貨鋪
在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-...