From d9e48a7c41625315c5cac262ecee715a89a17160 Mon Sep 17 00:00:00 2001 From: Christopher Ramey Date: Sun, 27 Jun 2021 09:57:16 -0800 Subject: [PATCH] code cleanup --- assets/assets.go | 83 ++++++++++++++++++++++++++++++++++++++++++++++++ pages/root.go | 31 +++++++----------- pages/static.go | 79 --------------------------------------------- 3 files changed, 95 insertions(+), 98 deletions(-) delete mode 100644 pages/static.go diff --git a/assets/assets.go b/assets/assets.go index 91dfa19..57cb6ca 100644 --- a/assets/assets.go +++ b/assets/assets.go @@ -1,7 +1,13 @@ package assets import ( + "bytes" + "compress/gzip" + "crypto/md5" "embed" + "fmt" + "net/http" + "strings" ) //go:embed *.ico *.html *.css @@ -10,3 +16,80 @@ var assets embed.FS func ReadFile(name string) ([]byte, error) { return assets.ReadFile(name) } + +type StaticContent struct { + Type string + Content []byte + ETag string + GZIPContent []byte + GZIPETag string +} + +func NewStaticContent(name string, mime string) (*StaticContent, error) { + // Load data + data, err := assets.ReadFile(name) + if err != nil { + return nil, err + } + sc := &StaticContent{Type: mime, Content: data} + + // Set a default Content-Type, if needed + if sc.Type == "" { + sc.Type = "application/octet-stream" + } + + // Populate ETag + sc.ETag = fmt.Sprintf("%x", md5.Sum(sc.Content)) + + var buf bytes.Buffer + gz, _ := gzip.NewWriterLevel(&buf, gzip.BestCompression) + defer gz.Close() + + if _, err := gz.Write(sc.Content); err != nil { + return nil, err + } + + if err := gz.Flush(); err != nil { + return nil, err + } + + // Using gzip encoding adds a minimum of 24 characters to the HTTP + // header, so only accept gzip encoding if we save that much or more + if (buf.Len() + 24) < len(sc.Content) { + sc.GZIPContent = buf.Bytes() + sc.GZIPETag = fmt.Sprintf("%x", md5.Sum(sc.GZIPContent)) + } + return sc, nil +} + +func (sc *StaticContent) ServeHTTP(w http.ResponseWriter, r *http.Request) { + gzok := strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") + gzlen := len(sc.GZIPContent) + + // Use the correct etag + var localETag string + if gzok && gzlen > 0 { + localETag = sc.GZIPETag + } else { + localETag = sc.ETag + } + + // Check the etag, maybe we don't need to send content + remoteETag := r.Header.Get("If-None-Match") + if localETag == remoteETag { + w.WriteHeader(http.StatusNotModified) + return + } + w.Header().Set("ETag", localETag) + w.Header().Set("Content-Type", sc.Type) + + // Finally, write our content + if gzok && gzlen > 0 { + w.Header().Set("Content-Encoding", "gzip") + w.Header().Set("Content-Length", fmt.Sprintf("%d", gzlen)) + w.Write(sc.GZIPContent) + } else { + w.Header().Set("Content-Length", fmt.Sprintf("%d", len(sc.Content))) + w.Write(sc.Content) + } +} diff --git a/pages/root.go b/pages/root.go index 520909e..443a0e1 100644 --- a/pages/root.go +++ b/pages/root.go @@ -2,9 +2,9 @@ package pages import ( "fmt" + "git.binarythought.com/cdramey/qurl/assets" "git.binarythought.com/cdramey/qurl/obj" "git.binarythought.com/cdramey/qurl/storage" - "git.binarythought.com/cdramey/qurl/assets" "html/template" "net/http" ) @@ -12,10 +12,10 @@ import ( type RootHandler struct { Storage storage.Storage - index *StaticContent - css *StaticContent - favi *StaticContent - usage *StaticContent + index *assets.StaticContent + css *assets.StaticContent + favi *assets.StaticContent + usage *assets.StaticContent submit *template.Template } @@ -67,40 +67,33 @@ func (ctx *RootHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { } func (ctx *RootHandler) Init() error { + var err error + // Initialize the static content object for the index page - data, err := assets.ReadFile("index.html") + ctx.index, err = assets.NewStaticContent("index.html", "text/html") if err != nil { return err } - ctx.index = &StaticContent{Type: "text/html", Content: data } - ctx.index.Init() // Initialize the static content object for the css - data, err = assets.ReadFile("qurl.css") + ctx.css, err = assets.NewStaticContent("qurl.css", "text/css") if err != nil { return err } - ctx.css = &StaticContent{Type: "text/css", Content: data } - ctx.css.Init() // Initialize the static content object favicon - data, err = assets.ReadFile("favicon.ico") + ctx.favi, err = assets.NewStaticContent("favicon.ico", "image/x-icon") if err != nil { return err } - ctx.favi = &StaticContent{Type: "image/x-icon", Content: data} - ctx.favi.Init() - // Initialize the api usage instructions - data, err = assets.ReadFile("usage.html") + ctx.usage, err = assets.NewStaticContent("usage.html", "text/html") if err != nil { return err } - ctx.usage = &StaticContent{Type: "text/html", Content: data} - ctx.usage.Init() // Initialize submit page template - data, err = assets.ReadFile("submit.html") + data, err := assets.ReadFile("submit.html") if err != nil { return err } diff --git a/pages/static.go b/pages/static.go deleted file mode 100644 index f89ffa2..0000000 --- a/pages/static.go +++ /dev/null @@ -1,79 +0,0 @@ -package pages - -import ( - "bytes" - "compress/gzip" - "crypto/md5" - "fmt" - "net/http" - "strings" -) - -type StaticContent struct { - Type string - Content []byte - ETag string - GZIPContent []byte - GZIPETag string -} - -func (sc *StaticContent) Init() { - // Populate ETag - sc.ETag = fmt.Sprintf("%x", md5.Sum(sc.Content)) - - // Set a default Content-Type, if needed - if sc.Type == "" { - sc.Type = "application/octet-stream" - } - - var buf bytes.Buffer - gz, _ := gzip.NewWriterLevel(&buf, gzip.BestCompression) - defer gz.Close() - - if _, err := gz.Write(sc.Content); err != nil { - return - } - - if err := gz.Flush(); err != nil { - return - } - - // Using gzip encoding adds a minimum of 24 characters to the HTTP - // header, so only accept gzip encoding if we save that much or more - if (buf.Len() + 24) < len(sc.Content) { - sc.GZIPContent = buf.Bytes() - sc.GZIPETag = fmt.Sprintf("%x", md5.Sum(sc.GZIPContent)) - } -} - -func (sc *StaticContent) ServeHTTP(w http.ResponseWriter, r *http.Request) { - gzok := strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") - gzlen := len(sc.GZIPContent) - - // Use the correct etag - var localETag string - if gzok && gzlen > 0 { - localETag = sc.GZIPETag - } else { - localETag = sc.ETag - } - - // Check the etag, maybe we don't need to send content - remoteETag := r.Header.Get("If-None-Match") - if localETag == remoteETag { - w.WriteHeader(http.StatusNotModified) - return - } - w.Header().Set("ETag", localETag) - w.Header().Set("Content-Type", sc.Type) - - // Finally, write our content - if gzok && gzlen > 0 { - w.Header().Set("Content-Encoding", "gzip") - w.Header().Set("Content-Length", fmt.Sprintf("%d", gzlen)) - w.Write(sc.GZIPContent) - } else { - w.Header().Set("Content-Length", fmt.Sprintf("%d", len(sc.Content))) - w.Write(sc.Content) - } -}