From 7204ae2e194465ec6c6c77fffd39274c39461df4 Mon Sep 17 00:00:00 2001 From: Maddie Zhan Date: Fri, 17 Sep 2021 21:06:00 +0800 Subject: [PATCH] Embed default assets --- README.md | 13 +++---- config/config.go | 3 +- go.mod | 2 +- .../fonts}/NotoSansDisplay-Light.ttf | Bin .../fonts}/NotoSansDisplay-Medium.ttf | Bin results/telemetry.go | 33 ++++++++--------- settings.toml | 6 ++-- {assets => web/assets}/index.html | 0 {assets => web/assets}/linode.html | 0 {assets => web/assets}/speedtest.js | 0 {assets => web/assets}/speedtest_worker.js | 0 web/web.go | 34 ++++++++++++++---- 12 files changed, 54 insertions(+), 37 deletions(-) rename {assets => results/fonts}/NotoSansDisplay-Light.ttf (100%) rename {assets => results/fonts}/NotoSansDisplay-Medium.ttf (100%) rename {assets => web/assets}/index.html (100%) rename {assets => web/assets}/linode.html (100%) rename {assets => web/assets}/speedtest.js (100%) rename {assets => web/assets}/speedtest_worker.js (100%) diff --git a/README.md b/README.md index 5f179d7..d9622e5 100644 --- a/README.md +++ b/README.md @@ -34,16 +34,16 @@ Works with mobile versions too. ## Installation -You need Go 1.13+ to compile the binary. If you have an older version of Go and don't want to install the tarball +You need Go 1.16+ to compile the binary. If you have an older version of Go and don't want to install the tarball manually, you can install newer version of Go into your `GOPATH`: -0. Install Go 1.14 +0. Install Go 1.17 ``` - $ go get golang.org/dl/go1.14.2 - # Assuming your GOPATH is default (~/go), Go 1.14.2 will be installed in ~/go/bin - $ ~/go/bin/go1.14.2 version - go version go1.14.2 linux/amd64 + $ go get golang.org/dl/go1.17.1 + # Assuming your GOPATH is default (~/go), Go 1.17.1 will be installed in ~/go/bin + $ ~/go/bin/go1.17.1 version + go version go1.17.1 linux/amd64 ``` 1. Clone this repository: @@ -98,6 +98,7 @@ manually, you can install newer version of Go into your `GOPATH`: ipinfo_api_key="" # assets directory path, defaults to `assets` in the same directory + # if the path cannot be found, embedded default assets will be used assets_path="./assets" # password for logging into statistics page, change this to enable stats page diff --git a/config/config.go b/config/config.go index 67d5efa..1934771 100644 --- a/config/config.go +++ b/config/config.go @@ -28,7 +28,7 @@ type Config struct { } var ( - configFile string = "" + configFile string loadedConfig *Config = nil ) @@ -40,7 +40,6 @@ func init() { viper.SetDefault("enable_cors", false) viper.SetDefault("statistics_password", "PASSWORD") viper.SetDefault("redact_ip_addresses", false) - viper.SetDefault("assets_path", "./assets") viper.SetDefault("database_type", "postgresql") viper.SetDefault("database_hostname", "localhost") viper.SetDefault("database_name", "speedtest") diff --git a/go.mod b/go.mod index 4c439a5..cd1b7ec 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/librespeed/speedtest -go 1.13 +go 1.16 require ( github.com/fsnotify/fsnotify v1.5.1 // indirect diff --git a/assets/NotoSansDisplay-Light.ttf b/results/fonts/NotoSansDisplay-Light.ttf similarity index 100% rename from assets/NotoSansDisplay-Light.ttf rename to results/fonts/NotoSansDisplay-Light.ttf diff --git a/assets/NotoSansDisplay-Medium.ttf b/results/fonts/NotoSansDisplay-Medium.ttf similarity index 100% rename from assets/NotoSansDisplay-Medium.ttf rename to results/fonts/NotoSansDisplay-Medium.ttf diff --git a/results/telemetry.go b/results/telemetry.go index 18a1ce7..ae91901 100644 --- a/results/telemetry.go +++ b/results/telemetry.go @@ -1,16 +1,15 @@ package results import ( + _ "embed" "encoding/json" "image" "image/color" "image/draw" "image/png" - "io/ioutil" "math/rand" "net" "net/http" - "path/filepath" "regexp" "strings" "time" @@ -37,6 +36,12 @@ const ( labelUpload = "Upload" ) +//go:embed fonts/NotoSansDisplay-Medium.ttf +var fontMediumBytes []byte + +//go:embed fonts/NotoSansDisplay-Light.ttf +var fontLightBytes []byte + var ( ipv4Regex = regexp.MustCompile(`(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)`) ipv6Regex = regexp.MustCompile(`(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4})?:)?((25[0-5]|(2[0-4]|1?[0-9])?[0-9])\.){3}(25[0-5]|(2[0-4]|1?[0-9])?[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1?[0-9])?[0-9])\.){3}(25[0-5]|(2[0-4]|1?[0-9])?[0-9]))`) @@ -83,25 +88,17 @@ type IPInfoResponse struct { func Initialize(c *config.Config) { // changed to use Noto Sans instead of OpenSans, due to issue: // https://github.com/golang/freetype/issues/8 - if b, err := ioutil.ReadFile(filepath.Join(c.AssetsPath, "NotoSansDisplay-Light.ttf")); err != nil { - log.Fatalf("Error opening NotoSansDisplay-Light font: %s", err) - } else { - f, err := freetype.ParseFont(b) - if err != nil { - log.Fatalf("Error parsing NotoSansDisplay-Light font: %s", err) - } - fontLight = f + fLight, err := freetype.ParseFont(fontLightBytes) + if err != nil { + log.Fatalf("Error parsing NotoSansDisplay-Light font: %s", err) } + fontLight = fLight - if b, err := ioutil.ReadFile(filepath.Join(c.AssetsPath, "NotoSansDisplay-Medium.ttf")); err != nil { - log.Fatalf("Error opening NotoSansDisplay-Medium font: %s", err) - } else { - f, err := freetype.ParseFont(b) - if err != nil { - log.Fatalf("Error parsing NotoSansDisplay-Medium font: %s", err) - } - fontBold = f + fMedium, err := freetype.ParseFont(fontMediumBytes) + if err != nil { + log.Fatalf("Error parsing NotoSansDisplay-Medium font: %s", err) } + fontBold = fMedium pingJitterLabelFace = truetype.NewFace(fontBold, &truetype.Options{ Size: 12, diff --git a/settings.toml b/settings.toml index 8e04b4a..aea076a 100644 --- a/settings.toml +++ b/settings.toml @@ -5,13 +5,13 @@ listen_port=8989 # proxy protocol port, use 0 to disable proxyprotocol_port=0 # Server location -server_lat=0 -server_lng=0 +server_lat=1 +server_lng=1 # ipinfo.io API key, if applicable ipinfo_api_key="" # assets directory path, defaults to `assets` in the same directory -assets_path="./assets" +assets_path="" # password for logging into statistics page statistics_password="PASSWORD" diff --git a/assets/index.html b/web/assets/index.html similarity index 100% rename from assets/index.html rename to web/assets/index.html diff --git a/assets/linode.html b/web/assets/linode.html similarity index 100% rename from assets/linode.html rename to web/assets/linode.html diff --git a/assets/speedtest.js b/web/assets/speedtest.js similarity index 100% rename from assets/speedtest.js rename to web/assets/speedtest.js diff --git a/assets/speedtest_worker.js b/web/assets/speedtest_worker.js similarity index 100% rename from assets/speedtest_worker.js rename to web/assets/speedtest_worker.js diff --git a/web/web.go b/web/web.go index 4269b14..990c83d 100644 --- a/web/web.go +++ b/web/web.go @@ -1,11 +1,14 @@ package web import ( + "embed" "encoding/json" "io" + "io/fs" "io/ioutil" "net" "net/http" + "os" "regexp" "strconv" "strings" @@ -26,6 +29,9 @@ const ( chunkSize = 1048576 ) +//go:embed assets +var defaultAssets embed.FS + var ( // generate random data for download test on start to minimize runtime overhead randomData = getRandomData(chunkSize) @@ -46,9 +52,21 @@ func ListenAndServe(conf *config.Config) error { r.Use(middleware.NoCache) r.Use(middleware.Recoverer) + var assetFS http.FileSystem + if fi, err := os.Stat(conf.AssetsPath); os.IsNotExist(err) || !fi.IsDir() { + log.Warnf("Configured asset path %s does not exist or is not a directory, using default assets", conf.AssetsPath) + sub, err := fs.Sub(defaultAssets, "assets") + if err != nil { + log.Fatalf("Failed when processing default assets: %s", err) + } + assetFS = http.FS(sub) + } else { + assetFS = justFilesFilesystem{fs: http.Dir(conf.AssetsPath), readDirBatchSize: 2} + } + addr := net.JoinHostPort(conf.BindAddress, conf.Port) log.Infof("Starting backend server on %s", addr) - r.Get("/*", pages) + r.Get("/*", pages(assetFS)) r.HandleFunc("/empty", empty) r.HandleFunc("/backend/empty", empty) r.Get("/garbage", garbage) @@ -96,14 +114,16 @@ func listenProxyProtocol(conf *config.Config, r *chi.Mux) { } } -func pages(w http.ResponseWriter, r *http.Request) { - if r.RequestURI == "/" { - r.RequestURI = "/index.html" +func pages(fs http.FileSystem) http.HandlerFunc { + fn := func(w http.ResponseWriter, r *http.Request) { + if r.RequestURI == "/" { + r.RequestURI = "/index.html" + } + + http.FileServer(fs).ServeHTTP(w, r) } - conf := config.LoadedConfig() - fs := justFilesFilesystem{fs: http.Dir(conf.AssetsPath), readDirBatchSize: 2} - http.FileServer(fs).ServeHTTP(w, r) + return fn } func empty(w http.ResponseWriter, r *http.Request) {