Add support for arbitrary asset files

This commit is contained in:
Knut Ahlers 2020-11-23 10:57:32 +01:00
parent 9d3b9d5c11
commit a52b9f5d15
Signed by: luzifer
GPG key ID: 0066F03ED215AD7D
3 changed files with 91 additions and 47 deletions

7
api.go
View file

@ -66,12 +66,9 @@ func (s *subcriptionStore) UnsubscribeSocket(id string) {
} }
func compileSocketMessage(msgType string, msg interface{}) socketMessage { func compileSocketMessage(msgType string, msg interface{}) socketMessage {
assetVersionsLock.RLock()
defer assetVersionsLock.RUnlock()
versionParts := []string{version} versionParts := []string{version}
for _, asset := range assets { for _, asset := range assetVersions.Keys() {
versionParts = append(versionParts, assetVersions[asset]) versionParts = append(versionParts, assetVersions.Get(asset))
} }
hash := sha256.New() hash := sha256.New()

79
assets.go Normal file
View file

@ -0,0 +1,79 @@
package main
import (
"crypto/sha256"
"fmt"
"io"
"os"
"path/filepath"
"sort"
"sync"
"github.com/pkg/errors"
)
var assetVersions = newAssetVersionStore()
type assetVersionStore struct {
store map[string]string
lock sync.RWMutex
}
func newAssetVersionStore() *assetVersionStore {
return &assetVersionStore{
store: make(map[string]string),
}
}
func (a *assetVersionStore) Get(key string) string {
a.lock.RLock()
defer a.lock.RUnlock()
return a.store[key]
}
func (a *assetVersionStore) Keys() []string {
a.lock.RLock()
defer a.lock.RUnlock()
var out []string
for k := range a.store {
out = append(out, k)
}
sort.Strings(out)
return out
}
func (a *assetVersionStore) UpdateAssetHashes(dir string) error {
a.lock.Lock()
defer a.lock.Unlock()
return filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
if err != nil {
// There was a previous error
return err
}
if info.IsDir() {
// We can't hash directories
return nil
}
hash := sha256.New()
f, err := os.Open(path)
if err != nil {
return errors.Wrap(err, "open asset file")
}
defer f.Close()
if _, err = io.Copy(hash, f); err != nil {
return errors.Wrap(err, "read asset file")
}
a.store[path] = fmt.Sprintf("%x", hash.Sum(nil))
return nil
})
}

52
main.go
View file

@ -1,19 +1,13 @@
package main package main
import ( import (
"crypto/sha256"
"fmt" "fmt"
"io"
"net/http" "net/http"
"os" "os"
"path"
"strings"
"sync"
"time" "time"
"github.com/gofrs/uuid" "github.com/gofrs/uuid"
"github.com/gorilla/mux" "github.com/gorilla/mux"
"github.com/pkg/errors"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
"github.com/Luzifer/rconfig/v2" "github.com/Luzifer/rconfig/v2"
@ -36,10 +30,6 @@ var (
WebHookTimeout time.Duration `flag:"webhook-timeout" default:"15m" description:"When to re-register the webhooks"` WebHookTimeout time.Duration `flag:"webhook-timeout" default:"15m" description:"When to re-register the webhooks"`
}{} }{}
assets = []string{"app.js", "overlay.html"}
assetVersions = map[string]string{}
assetVersionsLock = new(sync.RWMutex)
store *storage store *storage
webhookSecret = uuid.Must(uuid.NewV4()).String() webhookSecret = uuid.Must(uuid.NewV4()).String()
@ -70,20 +60,20 @@ func main() {
log.WithError(err).Fatal("Unable to load store") log.WithError(err).Fatal("Unable to load store")
} }
if err := updateAssetHashes(); err != nil { if err := assetVersions.UpdateAssetHashes(cfg.AssetDir); err != nil {
log.WithError(err).Fatal("Unable to read asset hashes") log.WithError(err).Fatal("Unable to read asset hashes")
} }
router := mux.NewRouter() var (
assetServer = http.FileServer(http.Dir(cfg.AssetDir))
router = mux.NewRouter()
)
registerAPI(router) registerAPI(router)
router.HandleFunc( router.PathPrefix("/public").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Sprintf("/{file:(?:%s)}", strings.Join(assets, "|")), w.Header().Set("Cache-Control", "no-cache")
func(w http.ResponseWriter, r *http.Request) { assetServer.ServeHTTP(w, r)
w.Header().Set("Cache-Control", "no-cache") })
http.ServeFile(w, r, path.Join(cfg.AssetDir, mux.Vars(r)["file"]))
},
)
go func() { go func() {
if err := http.ListenAndServe(cfg.Listen, router); err != nil { if err := http.ListenAndServe(cfg.Listen, router); err != nil {
@ -105,7 +95,7 @@ func main() {
for { for {
select { select {
case <-timerAssetCheck.C: case <-timerAssetCheck.C:
if err := updateAssetHashes(); err != nil { if err := assetVersions.UpdateAssetHashes(cfg.AssetDir); err != nil {
log.WithError(err).Error("Unable to update asset hashes") log.WithError(err).Error("Unable to update asset hashes")
} }
@ -127,25 +117,3 @@ func main() {
} }
} }
} }
func updateAssetHashes() error {
assetVersionsLock.Lock()
defer assetVersionsLock.Unlock()
for _, asset := range assets {
hash := sha256.New()
f, err := os.Open(asset)
if err != nil {
return errors.Wrap(err, "open asset file")
}
defer f.Close()
if _, err = io.Copy(hash, f); err != nil {
return errors.Wrap(err, "read asset file")
}
assetVersions[asset] = fmt.Sprintf("%x", hash.Sum(nil))
}
return nil
}