Enable gzip encoding static files for webgui

This commit is contained in:
Sergey Mishin 2015-04-04 20:06:20 +03:00
parent a5edb6807e
commit 77882e6086
5 changed files with 122 additions and 263 deletions

View File

@ -15,33 +15,32 @@ import (
"flag" "flag"
"go/format" "go/format"
"io" "io"
"net/http"
"os" "os"
"path/filepath" "path/filepath"
"strings" "strings"
"text/template" "text/template"
"time"
) )
var tpl = template.Must(template.New("assets").Parse(`package auto var tpl = template.Must(template.New("assets").Parse(`package auto
import ( import (
"bytes"
"compress/gzip"
"encoding/base64" "encoding/base64"
"io/ioutil" )
const (
AssetsBuildDate = "{{.BuildDate}}"
) )
func Assets() map[string][]byte { func Assets() map[string][]byte {
var assets = make(map[string][]byte, {{.assets | len}}) var assets = make(map[string][]byte, {{.Assets | len}})
var bs []byte {{range $asset := .Assets}}
var gr *gzip.Reader assets["{{$asset.Name}}"], _ = base64.StdEncoding.DecodeString("{{$asset.Data}}")
{{range $asset := .assets}}
bs, _ = base64.StdEncoding.DecodeString("{{$asset.Data}}")
gr, _ = gzip.NewReader(bytes.NewReader(bs))
bs, _ = ioutil.ReadAll(gr)
assets["{{$asset.Name}}"] = bs
{{end}} {{end}}
return assets return assets
} }
`)) `))
type asset struct { type asset struct {
@ -86,12 +85,20 @@ func walkerFor(basePath string) filepath.WalkFunc {
} }
} }
type templateVars struct {
Assets []asset
BuildDate string
}
func main() { func main() {
flag.Parse() flag.Parse()
filepath.Walk(flag.Arg(0), walkerFor(flag.Arg(0))) filepath.Walk(flag.Arg(0), walkerFor(flag.Arg(0)))
var buf bytes.Buffer var buf bytes.Buffer
tpl.Execute(&buf, map[string][]asset{"assets": assets}) tpl.Execute(&buf, templateVars{
Assets: assets,
BuildDate: time.Now().UTC().Format(http.TimeFormat),
})
bs, err := format.Source(buf.Bytes()) bs, err := format.Source(buf.Bytes())
if err != nil { if err != nil {
panic(err) panic(err)

View File

@ -7,6 +7,8 @@
package main package main
import ( import (
"bytes"
"compress/gzip"
"crypto/tls" "crypto/tls"
"encoding/json" "encoding/json"
"fmt" "fmt"
@ -45,7 +47,6 @@ var (
configInSync = true configInSync = true
guiErrors = []guiError{} guiErrors = []guiError{}
guiErrorsMut sync.Mutex guiErrorsMut sync.Mutex
modt = time.Now().UTC().Format(http.TimeFormat)
eventSub *events.BufferedSubscription eventSub *events.BufferedSubscription
) )
@ -832,8 +833,17 @@ func embeddedStatic(assetDir string) http.Handler {
if len(mtype) != 0 { if len(mtype) != 0 {
w.Header().Set("Content-Type", mtype) w.Header().Set("Content-Type", mtype)
} }
if strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") {
w.Header().Set("Content-Encoding", "gzip")
} else {
// ungzip if browser not send gzip accepted header
var gr *gzip.Reader
gr, _ = gzip.NewReader(bytes.NewReader(bs))
bs, _ = ioutil.ReadAll(gr)
gr.Close()
}
w.Header().Set("Content-Length", fmt.Sprintf("%d", len(bs))) w.Header().Set("Content-Length", fmt.Sprintf("%d", len(bs)))
w.Header().Set("Last-Modified", modt) w.Header().Set("Last-Modified", auto.AssetsBuildDate)
w.Write(bs) w.Write(bs)
}) })

View File

@ -8,6 +8,8 @@ package auto_test
import ( import (
"bytes" "bytes"
"compress/gzip"
"io/ioutil"
"testing" "testing"
"github.com/syncthing/syncthing/internal/auto" "github.com/syncthing/syncthing/internal/auto"
@ -19,6 +21,11 @@ func TestAssets(t *testing.T) {
if !ok { if !ok {
t.Fatal("No index.html in compiled in assets") t.Fatal("No index.html in compiled in assets")
} }
var gr *gzip.Reader
gr, _ = gzip.NewReader(bytes.NewReader(idx))
idx, _ = ioutil.ReadAll(gr)
if !bytes.Contains(idx, []byte("<html")) { if !bytes.Contains(idx, []byte("<html")) {
t.Fatal("No html in index.html") t.Fatal("No html in index.html")
} }

File diff suppressed because one or more lines are too long

View File

@ -9,7 +9,9 @@
package integration package integration
import ( import (
"bytes"
"encoding/json" "encoding/json"
"io/ioutil"
"net/http" "net/http"
"strings" "strings"
"testing" "testing"
@ -49,8 +51,15 @@ func TestGetIndex(t *testing.T) {
if res.StatusCode != 200 { if res.StatusCode != 200 {
t.Errorf("Status %d != 200", res.StatusCode) t.Errorf("Status %d != 200", res.StatusCode)
} }
if res.ContentLength < 1024 { bs, err := ioutil.ReadAll(res.Body)
t.Errorf("Length %d < 1024", res.ContentLength) if err != nil {
t.Fatal(err)
}
if len(bs) < 1024 {
t.Errorf("Length %d < 1024", len(bs))
}
if !bytes.Contains(bs, []byte("</html>")) {
t.Error("Incorrect response")
} }
if res.Header.Get("Set-Cookie") == "" { if res.Header.Get("Set-Cookie") == "" {
t.Error("No set-cookie header") t.Error("No set-cookie header")
@ -64,8 +73,15 @@ func TestGetIndex(t *testing.T) {
if res.StatusCode != 200 { if res.StatusCode != 200 {
t.Errorf("Status %d != 200", res.StatusCode) t.Errorf("Status %d != 200", res.StatusCode)
} }
if res.ContentLength < 1024 { bs, err = ioutil.ReadAll(res.Body)
t.Errorf("Length %d < 1024", res.ContentLength) if err != nil {
t.Fatal(err)
}
if len(bs) < 1024 {
t.Errorf("Length %d < 1024", len(bs))
}
if !bytes.Contains(bs, []byte("</html>")) {
t.Error("Incorrect response")
} }
if res.Header.Get("Set-Cookie") == "" { if res.Header.Get("Set-Cookie") == "" {
t.Error("No set-cookie header") t.Error("No set-cookie header")