Mit HTTP/2 Push holt sich der Browser eine HTML Datei vom Server. Der Server erkennt, dass die CSS Styledatei auch geladen werden wird, und löst ein HTTP/2 Push an den Browser bezogen auf die CSS Datei aus.Der Browser lädt die CSS Datei parallel vom Server, also gleichzeitig mit der HTML Datei. Damit wird die Site schneller geladen:
# Key considerations for algorithm "RSA" ≥ 2048-bit
openssl genrsa -out server.key 2048
# Key considerations for algorithm "ECDSA" ≥ secp384r1
# List ECDSA the supported curves (openssl ecparam -list_curves)
openssl ecparam -genkey -name secp384r1 -out server.key
# Generation of self-signed(x509) public key (PEM-encodings .pem|.crt) based on the private (.key)
openssl req -new -x509 -sha256 -key server.key -out server.crt -days 3650
Die erstellten Dateien server.crt und server.key referenzieren wir im nachfolgenden Go Code.package main
import (
"log"
"net/http"
"os"
"path/filepath"
"golang.org/x/net/http2"
)
func main() {
port := "443"
if len(os.Args) > 1 {
port = os.Args[1]
}
srv := &http.Server{
Addr: ":" + port,
Handler: HTTPHandler(),
}
http2.ConfigureServer(srv, &http2.Server{})
log.Fatal(srv.ListenAndServeTLS("server.crt", "server.key"))
}
func HTTPHandler() http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
path := r.URL.Path
if path == "/" {
pusher, ok := w.(http.Pusher)
if ok {
options := &http.PushOptions{
Header: http.Header {
"Accept-Encoding": r.Header["Accept-Encoding"],
},
}
pusher.Push("/css/main.css", options)
}
}
workingPath, _ := os.Getwd()
realPath := filepath.Join(workingPath, path)
stat, err := os.Stat(realPath)
if err != nil {
if os.IsNotExist(err) {
log.Println(realPath + " does not exist")
return
}
}
if stat.IsDir() {
realPath = filepath.Join(realPath, "index.html")
if stat, err = os.Stat(realPath); err != nil {
if os.IsNotExist(err) {
log.Println(realPath + " not found")
}
}
}
log.Println("serve file " + realPath)
http.ServeFile(w, r, realPath)
})
}
Der Aufbau entspricht einem normalen HTTP Server über die http.Server Instanz. Dieser wird mit dem folgenden Befehl zu einem HTTP/2 Server:
http2.ConfigureServer(srv, &http2.Server{})
Die HTTP/2 Push Funktion erfolgt über die http.Pusher Abfrage. Solche ist ok true wenn der Server dies unterstützt:
pusher, ok := w.(http.Pusher)
if ok {
options := &http.PushOptions{
Header: http.Header {
"Accept-Encoding": r.Header["Accept-Encoding"],
},
}
pusher.Push("/css/main.css", options)
}
Das Accept-Encoding ist wichtig, wenn z.B. die GZip Unterstützung benötigt wird.