From 0e3dde4cf111fed9c7b1b3f1cbf0cbb70024c549 Mon Sep 17 00:00:00 2001 From: Daniel Date: Tue, 30 Aug 2022 16:11:52 +0200 Subject: [PATCH] Switch to zipfs lib for loading files from a zip --- ui/api.go | 16 ++++++++-------- ui/serve.go | 52 ++++++++++++++++++++++++---------------------------- 2 files changed, 32 insertions(+), 36 deletions(-) diff --git a/ui/api.go b/ui/api.go index 68c9fbe9..9eb5f6e1 100644 --- a/ui/api.go +++ b/ui/api.go @@ -1,8 +1,6 @@ package ui import ( - resources "github.com/cookieo9/resources-go" - "github.com/safing/portbase/api" "github.com/safing/portbase/log" ) @@ -22,16 +20,18 @@ func reloadUI(_ *api.Request) (msg string, err error) { appsLock.Lock() defer appsLock.Unlock() - // close all bundles. - for id, bundle := range apps { - err := bundle.Close() + // Close all archives. + for id, archiveFS := range apps { + err := archiveFS.Close() if err != nil { - log.Warningf("ui: failed to close bundle %s: %s", id, err) + log.Warningf("ui: failed to close archive %s: %s", id, err) } } // Reset index. - apps = make(map[string]*resources.BundleSequence) + for key := range apps { + delete(apps, key) + } - return "all ui bundles successfully reloaded", nil + return "all ui archives successfully reloaded", nil } diff --git a/ui/serve.go b/ui/serve.go index 64509f30..1d80a059 100644 --- a/ui/serve.go +++ b/ui/serve.go @@ -6,11 +6,12 @@ import ( "io" "net/http" "net/url" + "os" "path/filepath" "strings" "sync" - resources "github.com/cookieo9/resources-go" + "github.com/spkg/zipfs" "github.com/safing/portbase/api" "github.com/safing/portbase/log" @@ -20,7 +21,7 @@ import ( ) var ( - apps = make(map[string]*resources.BundleSequence) + apps = make(map[string]*zipfs.FileSystem) appsLock sync.RWMutex ) @@ -28,7 +29,7 @@ func registerRoutes() error { // Server assets. api.RegisterHandler( "/assets/{resPath:[a-zA-Z0-9/\\._-]+}", - &bundleServer{defaultModuleName: "assets"}, + &archiveServer{defaultModuleName: "assets"}, ) // Add slash to plain module namespaces. @@ -38,7 +39,7 @@ func registerRoutes() error { ) // Serve modules. - srv := &bundleServer{} + srv := &archiveServer{} api.RegisterHandler("/ui/modules/{moduleName:[a-z]+}/", srv) api.RegisterHandler("/ui/modules/{moduleName:[a-z]+}/{resPath:[a-zA-Z0-9/\\._-]+}", srv) @@ -51,17 +52,17 @@ func registerRoutes() error { return nil } -type bundleServer struct { +type archiveServer struct { defaultModuleName string } -func (bs *bundleServer) BelongsTo() *modules.Module { return module } +func (bs *archiveServer) BelongsTo() *modules.Module { return module } -func (bs *bundleServer) ReadPermission(*http.Request) api.Permission { return api.PermitAnyone } +func (bs *archiveServer) ReadPermission(*http.Request) api.Permission { return api.PermitAnyone } -func (bs *bundleServer) WritePermission(*http.Request) api.Permission { return api.NotSupported } +func (bs *archiveServer) WritePermission(*http.Request) api.Permission { return api.NotSupported } -func (bs *bundleServer) ServeHTTP(w http.ResponseWriter, r *http.Request) { +func (bs *archiveServer) ServeHTTP(w http.ResponseWriter, r *http.Request) { // Get request context. ar := api.GetAPIRequest(r) if ar == nil { @@ -85,10 +86,10 @@ func (bs *bundleServer) ServeHTTP(w http.ResponseWriter, r *http.Request) { } appsLock.RLock() - bundle, ok := apps[moduleName] + archiveFS, ok := apps[moduleName] appsLock.RUnlock() if ok { - ServeFileFromBundle(w, r, moduleName, bundle, resPath) + ServeFileFromArchive(w, r, moduleName, archiveFS, resPath) return } @@ -105,39 +106,38 @@ func (bs *bundleServer) ServeHTTP(w http.ResponseWriter, r *http.Request) { return } - // open bundle - newBundle, err := resources.OpenZip(zipFile.Path()) + // Open archive from disk. + archiveFS, err = zipfs.New(zipFile.Path()) if err != nil { log.Tracef("ui: error prepping module %s: %s", moduleName, err) http.Error(w, err.Error(), http.StatusInternalServerError) return } - bundle = &resources.BundleSequence{newBundle} appsLock.Lock() - apps[moduleName] = bundle + apps[moduleName] = archiveFS appsLock.Unlock() - ServeFileFromBundle(w, r, moduleName, bundle, resPath) + ServeFileFromArchive(w, r, moduleName, archiveFS, resPath) } -// ServeFileFromBundle serves a file from the given bundle. -func ServeFileFromBundle(w http.ResponseWriter, r *http.Request, bundleName string, bundle *resources.BundleSequence, path string) { - readCloser, err := bundle.Open(path) +// ServeFileFromArchive serves a file from the given archive. +func ServeFileFromArchive(w http.ResponseWriter, r *http.Request, archiveName string, archiveFS *zipfs.FileSystem, path string) { + readCloser, err := archiveFS.Open(path) if err != nil { - if errors.Is(err, resources.ErrNotFound) { + if os.IsNotExist(err) { // Check if there is a base index.html file we can serve instead. var indexErr error path = "index.html" - readCloser, indexErr = bundle.Open(path) + readCloser, indexErr = archiveFS.Open(path) if indexErr != nil { // If we cannot get an index, continue with handling the original error. - log.Tracef("ui: requested resource \"%s\" not found in bundle %s: %s", path, bundleName, err) + log.Tracef("ui: requested resource \"%s\" not found in archive %s: %s", path, archiveName, err) http.Error(w, err.Error(), http.StatusNotFound) return } } else { - log.Tracef("ui: error opening module %s: %s", bundleName, err) + log.Tracef("ui: error opening module %s: %s", archiveName, err) http.Error(w, err.Error(), http.StatusInternalServerError) return } @@ -152,12 +152,8 @@ func ServeFileFromBundle(w http.ResponseWriter, r *http.Request, bundleName stri } } - // TODO: Set content security policy - // For some reason, this breaks the ui client - // w.Header().Set("Content-Security-Policy", "default-src 'self'") - w.WriteHeader(http.StatusOK) - if r.Method != "HEAD" { + if r.Method != http.MethodHead { _, err = io.Copy(w, readCloser) if err != nil { log.Errorf("ui: failed to serve file: %s", err)