5
0
mirror of https://github.com/wailsapp/wails.git synced 2025-05-02 22:00:19 +08:00

Chore/refactor assetserver (#2250)

* Remove context from API calls

* Remove logger dependency

* Remove fs dependency

* Remove runtime dependency

* Update Windows/Linux calls to NewAssetServerMainPage

* Add missing imports

* fix runtime import clash
This commit is contained in:
Lea Anthony 2022-12-31 10:36:07 +11:00 committed by GitHub
parent 66bc258f81
commit d3b4105f75
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 176 additions and 70 deletions

View File

@ -2,7 +2,6 @@ package assetserver
import ( import (
"bytes" "bytes"
"context"
"embed" "embed"
"errors" "errors"
"fmt" "fmt"
@ -13,11 +12,14 @@ import (
"path" "path"
"strings" "strings"
"github.com/wailsapp/wails/v2/internal/fs"
"github.com/wailsapp/wails/v2/internal/logger"
"github.com/wailsapp/wails/v2/pkg/options/assetserver" "github.com/wailsapp/wails/v2/pkg/options/assetserver"
) )
type Logger interface {
Debug(message string, args ...interface{})
Error(message string, args ...interface{})
}
//go:embed defaultindex.html //go:embed defaultindex.html
var defaultHTML []byte var defaultHTML []byte
@ -29,16 +31,12 @@ type assetHandler struct {
fs iofs.FS fs iofs.FS
handler http.Handler handler http.Handler
logger *logger.Logger logger Logger
retryMissingFiles bool retryMissingFiles bool
} }
func NewAssetHandler(ctx context.Context, options assetserver.Options) (http.Handler, error) { func NewAssetHandler(options assetserver.Options, log Logger) (http.Handler, error) {
var log *logger.Logger
if _logger := ctx.Value("logger"); _logger != nil {
log = _logger.(*logger.Logger)
}
vfs := options.Assets vfs := options.Assets
if vfs != nil { if vfs != nil {
@ -46,12 +44,12 @@ func NewAssetHandler(ctx context.Context, options assetserver.Options) (http.Han
return nil, err return nil, err
} }
subDir, err := fs.FindPathToFile(vfs, indexHTML) subDir, err := FindPathToFile(vfs, indexHTML)
if err != nil { if err != nil {
if errors.Is(err, os.ErrNotExist) { if errors.Is(err, os.ErrNotExist) {
msg := "no `index.html` could be found in your Assets fs.FS" msg := "no `index.html` could be found in your Assets fs.FS"
if embedFs, isEmbedFs := vfs.(embed.FS); isEmbedFs { if embedFs, isEmbedFs := vfs.(embed.FS); isEmbedFs {
rootFolder, _ := fs.FindEmbedRootPath(embedFs) rootFolder, _ := FindEmbedRootPath(embedFs)
msg += fmt.Sprintf(", please make sure the embedded directory '%s' is correct and contains your assets", rootFolder) msg += fmt.Sprintf(", please make sure the embedded directory '%s' is correct and contains your assets", rootFolder)
} }

View File

@ -2,7 +2,6 @@ package assetserver
import ( import (
"bytes" "bytes"
"context"
"fmt" "fmt"
"net/http" "net/http"
"net/http/httptest" "net/http/httptest"
@ -10,8 +9,6 @@ import (
"golang.org/x/net/html" "golang.org/x/net/html"
"github.com/wailsapp/wails/v2/internal/frontend/runtime"
"github.com/wailsapp/wails/v2/internal/logger"
"github.com/wailsapp/wails/v2/pkg/options" "github.com/wailsapp/wails/v2/pkg/options"
"github.com/wailsapp/wails/v2/pkg/options/assetserver" "github.com/wailsapp/wails/v2/pkg/options/assetserver"
) )
@ -21,41 +18,48 @@ const (
ipcJSPath = "/wails/ipc.js" ipcJSPath = "/wails/ipc.js"
) )
type RuntimeAssets interface {
DesktopIPC() []byte
WebsocketIPC() []byte
RuntimeDesktopJS() []byte
}
type AssetServer struct { type AssetServer struct {
handler http.Handler handler http.Handler
wsHandler http.Handler wsHandler http.Handler
runtimeJS []byte runtimeJS []byte
ipcJS func(*http.Request) []byte ipcJS func(*http.Request) []byte
logger *logger.Logger logger Logger
runtime RuntimeAssets
servingFromDisk bool servingFromDisk bool
appendSpinnerToBody bool appendSpinnerToBody bool
} }
func NewAssetServerMainPage(ctx context.Context, bindingsJSON string, options *options.App) (*AssetServer, error) { func NewAssetServerMainPage(bindingsJSON string, options *options.App, servingFromDisk bool, logger Logger, runtime RuntimeAssets) (*AssetServer, error) {
assetOptions, err := BuildAssetServerConfig(options) assetOptions, err := BuildAssetServerConfig(options)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return NewAssetServer(ctx, bindingsJSON, assetOptions) return NewAssetServer(bindingsJSON, assetOptions, servingFromDisk, logger, runtime)
} }
func NewAssetServer(ctx context.Context, bindingsJSON string, options assetserver.Options) (*AssetServer, error) { func NewAssetServer(bindingsJSON string, options assetserver.Options, servingFromDisk bool, logger Logger, runtime RuntimeAssets) (*AssetServer, error) {
handler, err := NewAssetHandler(ctx, options) handler, err := NewAssetHandler(options, logger)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return NewAssetServerWithHandler(ctx, handler, bindingsJSON) return NewAssetServerWithHandler(handler, bindingsJSON, servingFromDisk, logger, runtime)
} }
func NewAssetServerWithHandler(ctx context.Context, handler http.Handler, bindingsJSON string) (*AssetServer, error) { func NewAssetServerWithHandler(handler http.Handler, bindingsJSON string, servingFromDisk bool, logger Logger, runtime RuntimeAssets) (*AssetServer, error) {
var buffer bytes.Buffer var buffer bytes.Buffer
if bindingsJSON != "" { if bindingsJSON != "" {
buffer.WriteString(`window.wailsbindings='` + bindingsJSON + `';` + "\n") buffer.WriteString(`window.wailsbindings='` + bindingsJSON + `';` + "\n")
} }
buffer.Write(runtime.RuntimeDesktopJS) buffer.Write(runtime.RuntimeDesktopJS())
result := &AssetServer{ result := &AssetServer{
handler: handler, handler: handler,
@ -65,11 +69,9 @@ func NewAssetServerWithHandler(ctx context.Context, handler http.Handler, bindin
// If so, this means we are in dev mode and are serving assets off disk. // If so, this means we are in dev mode and are serving assets off disk.
// We indicate this through the `servingFromDisk` flag to ensure requests // We indicate this through the `servingFromDisk` flag to ensure requests
// aren't cached in dev mode. // aren't cached in dev mode.
servingFromDisk: ctx.Value("assetdir") != nil, servingFromDisk: servingFromDisk,
} logger: logger,
runtime: runtime,
if _logger := ctx.Value("logger"); _logger != nil {
result.logger = _logger.(*logger.Logger)
} }
return result, nil return result, nil
@ -121,7 +123,7 @@ func (d *AssetServer) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
d.writeBlob(rw, path, d.runtimeJS) d.writeBlob(rw, path, d.runtimeJS)
case ipcJSPath: case ipcJSPath:
content := runtime.DesktopIPC content := d.runtime.DesktopIPC()
if d.ipcJS != nil { if d.ipcJS != nil {
content = d.ipcJS(req) content = d.ipcJS(req)
} }

View File

@ -4,11 +4,8 @@
package assetserver package assetserver
import ( import (
"context"
"net/http" "net/http"
"strings" "strings"
"github.com/wailsapp/wails/v2/internal/frontend/runtime"
) )
/* /*
@ -16,8 +13,8 @@ The assetserver for the dev mode.
Depending on the UserAgent it injects a websocket based IPC script into `index.html` or the default desktop IPC. The Depending on the UserAgent it injects a websocket based IPC script into `index.html` or the default desktop IPC. The
default desktop IPC is injected when the webview accesses the devserver. default desktop IPC is injected when the webview accesses the devserver.
*/ */
func NewDevAssetServer(ctx context.Context, handler http.Handler, wsHandler http.Handler, bindingsJSON string) (*AssetServer, error) { func NewDevAssetServer(handler http.Handler, wsHandler http.Handler, bindingsJSON string, servingFromDisk bool, logger Logger, runtime RuntimeAssets) (*AssetServer, error) {
result, err := NewAssetServerWithHandler(ctx, handler, bindingsJSON) result, err := NewAssetServerWithHandler(handler, bindingsJSON, servingFromDisk, logger, runtime)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -26,9 +23,9 @@ func NewDevAssetServer(ctx context.Context, handler http.Handler, wsHandler http
result.appendSpinnerToBody = true result.appendSpinnerToBody = true
result.ipcJS = func(req *http.Request) []byte { result.ipcJS = func(req *http.Request) []byte {
if strings.Contains(req.UserAgent(), WailsUserAgentValue) { if strings.Contains(req.UserAgent(), WailsUserAgentValue) {
return runtime.DesktopIPC return runtime.DesktopIPC()
} }
return runtime.WebsocketIPC return runtime.WebsocketIPC()
} }
return result, nil return result, nil

View File

@ -0,0 +1,75 @@
package assetserver
import (
"embed"
"fmt"
"io/fs"
"os"
"path/filepath"
"strings"
)
// FindEmbedRootPath finds the root path in the embed FS. It's the directory which contains all the files.
func FindEmbedRootPath(fsys embed.FS) (string, error) {
stopErr := fmt.Errorf("files or multiple dirs found")
fPath := ""
err := fs.WalkDir(fsys, ".", func(path string, d fs.DirEntry, err error) error {
if err != nil {
return err
}
if d.IsDir() {
fPath = path
if entries, dErr := fs.ReadDir(fsys, path); dErr != nil {
return dErr
} else if len(entries) <= 1 {
return nil
}
}
return stopErr
})
if err != nil && err != stopErr {
return "", err
}
return fPath, nil
}
func FindPathToFile(fsys fs.FS, file string) (string, error) {
stat, _ := fs.Stat(fsys, file)
if stat != nil {
return ".", nil
}
var indexFiles []string
err := fs.WalkDir(fsys, ".", func(path string, d fs.DirEntry, err error) error {
if err != nil {
return err
}
if strings.HasSuffix(path, file) {
indexFiles = append(indexFiles, path)
}
return nil
})
if err != nil {
return "", err
}
if len(indexFiles) > 1 {
selected := indexFiles[0]
for _, f := range indexFiles {
if len(f) < len(selected) {
selected = f
}
}
path, _ := filepath.Split(selected)
return path, nil
}
if len(indexFiles) > 0 {
path, _ := filepath.Split(indexFiles[0])
return path, nil
}
return "", fmt.Errorf("%s: %w", file, os.ErrNotExist)
}

View File

@ -26,6 +26,7 @@ import (
"github.com/wailsapp/wails/v2/internal/binding" "github.com/wailsapp/wails/v2/internal/binding"
"github.com/wailsapp/wails/v2/internal/frontend" "github.com/wailsapp/wails/v2/internal/frontend"
"github.com/wailsapp/wails/v2/internal/frontend/assetserver" "github.com/wailsapp/wails/v2/internal/frontend/assetserver"
"github.com/wailsapp/wails/v2/internal/frontend/runtime"
"github.com/wailsapp/wails/v2/internal/logger" "github.com/wailsapp/wails/v2/internal/logger"
"github.com/wailsapp/wails/v2/pkg/options" "github.com/wailsapp/wails/v2/pkg/options"
) )
@ -86,7 +87,8 @@ func NewFrontend(ctx context.Context, appoptions *options.App, myLogger *logger.
} else { } else {
appBindings.DB().UpdateObfuscatedCallMap() appBindings.DB().UpdateObfuscatedCallMap()
} }
assets, err := assetserver.NewAssetServerMainPage(ctx, bindings, appoptions)
assets, err := assetserver.NewAssetServerMainPage(bindings, appoptions, ctx.Value("assetdir") != nil, myLogger, runtime.RuntimeAssetsBundle)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }

View File

@ -91,6 +91,7 @@ import (
"github.com/wailsapp/wails/v2/internal/binding" "github.com/wailsapp/wails/v2/internal/binding"
"github.com/wailsapp/wails/v2/internal/frontend" "github.com/wailsapp/wails/v2/internal/frontend"
"github.com/wailsapp/wails/v2/internal/frontend/assetserver" "github.com/wailsapp/wails/v2/internal/frontend/assetserver"
wailsruntime "github.com/wailsapp/wails/v2/internal/frontend/runtime"
"github.com/wailsapp/wails/v2/internal/logger" "github.com/wailsapp/wails/v2/internal/logger"
"github.com/wailsapp/wails/v2/pkg/options" "github.com/wailsapp/wails/v2/pkg/options"
) )
@ -159,7 +160,7 @@ func NewFrontend(ctx context.Context, appoptions *options.App, myLogger *logger.
} else { } else {
appBindings.DB().UpdateObfuscatedCallMap() appBindings.DB().UpdateObfuscatedCallMap()
} }
assets, err := assetserver.NewAssetServerMainPage(ctx, bindings, appoptions) assets, err := assetserver.NewAssetServerMainPage(bindings, appoptions, ctx.Value("assetdir") != nil, myLogger, wailsruntime.RuntimeAssetsBundle)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }

View File

@ -27,6 +27,7 @@ import (
"github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/win32" "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/win32"
"github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc" "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc"
"github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc/w32" "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc/w32"
wailsruntime "github.com/wailsapp/wails/v2/internal/frontend/runtime"
"github.com/wailsapp/wails/v2/internal/logger" "github.com/wailsapp/wails/v2/internal/logger"
"github.com/wailsapp/wails/v2/internal/system/operatingsystem" "github.com/wailsapp/wails/v2/internal/system/operatingsystem"
"github.com/wailsapp/wails/v2/pkg/options" "github.com/wailsapp/wails/v2/pkg/options"
@ -102,7 +103,7 @@ func NewFrontend(ctx context.Context, appoptions *options.App, myLogger *logger.
appBindings.DB().UpdateObfuscatedCallMap() appBindings.DB().UpdateObfuscatedCallMap()
} }
assets, err := assetserver.NewAssetServerMainPage(ctx, bindings, appoptions) assets, err := assetserver.NewAssetServerMainPage(bindings, appoptions, ctx.Value("assetdir") != nil, myLogger, wailsruntime.RuntimeAssetsBundle)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }

View File

@ -18,6 +18,8 @@ import (
"sync" "sync"
"time" "time"
"github.com/wailsapp/wails/v2/internal/frontend/runtime"
"github.com/labstack/echo/v4" "github.com/labstack/echo/v4"
"github.com/wailsapp/wails/v2/internal/binding" "github.com/wailsapp/wails/v2/internal/binding"
"github.com/wailsapp/wails/v2/internal/frontend" "github.com/wailsapp/wails/v2/internal/frontend"
@ -61,6 +63,8 @@ func (d *DevWebServer) Run(ctx context.Context) error {
var assetHandler http.Handler var assetHandler http.Handler
var wsHandler http.Handler var wsHandler http.Handler
var myLogger *logger.Logger
_fronendDevServerURL, _ := ctx.Value("frontenddevserverurl").(string) _fronendDevServerURL, _ := ctx.Value("frontenddevserverurl").(string)
if _fronendDevServerURL == "" { if _fronendDevServerURL == "" {
assetdir, _ := ctx.Value("assetdir").(string) assetdir, _ := ctx.Value("assetdir").(string)
@ -68,8 +72,11 @@ func (d *DevWebServer) Run(ctx context.Context) error {
return c.String(http.StatusOK, assetdir) return c.String(http.StatusOK, assetdir)
}) })
if _logger := ctx.Value("logger"); _logger != nil {
myLogger = _logger.(*logger.Logger)
}
var err error var err error
assetHandler, err = assetserver.NewAssetHandler(ctx, assetServerConfig) assetHandler, err = assetserver.NewAssetHandler(assetServerConfig, myLogger)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
@ -101,7 +108,7 @@ func (d *DevWebServer) Run(ctx context.Context) error {
log.Fatal(err) log.Fatal(err)
} }
assetServer, err := assetserver.NewDevAssetServer(ctx, assetHandler, wsHandler, bindingsJSON) assetServer, err := assetserver.NewDevAssetServer(assetHandler, wsHandler, bindingsJSON, ctx.Value("assetdir") != nil, myLogger, runtime.RuntimeAssetsBundle)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }

View File

@ -0,0 +1,26 @@
//go:build !dev
package runtime
var RuntimeAssetsBundle = &RuntimeAssets{
desktopIPC: DesktopIPC,
runtimeDesktopJS: RuntimeDesktopJS,
}
type RuntimeAssets struct {
desktopIPC []byte
websocketIPC []byte
runtimeDesktopJS []byte
}
func (r *RuntimeAssets) DesktopIPC() []byte {
return r.desktopIPC
}
func (r *RuntimeAssets) WebsocketIPC() []byte {
return r.websocketIPC
}
func (r *RuntimeAssets) RuntimeDesktopJS() []byte {
return r.runtimeDesktopJS
}

View File

@ -0,0 +1,27 @@
//go:build dev
package runtime
var RuntimeAssetsBundle = &RuntimeAssets{
desktopIPC: DesktopIPC,
websocketIPC: WebsocketIPC,
runtimeDesktopJS: RuntimeDesktopJS,
}
type RuntimeAssets struct {
desktopIPC []byte
websocketIPC []byte
runtimeDesktopJS []byte
}
func (r *RuntimeAssets) DesktopIPC() []byte {
return r.desktopIPC
}
func (r *RuntimeAssets) WebsocketIPC() []byte {
return r.websocketIPC
}
func (r *RuntimeAssets) RuntimeDesktopJS() []byte {
return r.runtimeDesktopJS
}

View File

@ -2,7 +2,6 @@ package fs
import ( import (
"crypto/md5" "crypto/md5"
"embed"
"fmt" "fmt"
"io" "io"
"io/fs" "io/fs"
@ -403,32 +402,3 @@ func FindFileInParents(path string, filename string) string {
} }
return pathToFile return pathToFile
} }
// FindEmbedRootPath finds the root path in the embed FS. It's the directory which contains all the files.
func FindEmbedRootPath(fsys embed.FS) (string, error) {
stopErr := fmt.Errorf("files or multiple dirs found")
fPath := ""
err := fs.WalkDir(fsys, ".", func(path string, d fs.DirEntry, err error) error {
if err != nil {
return err
}
if d.IsDir() {
fPath = path
if entries, dErr := fs.ReadDir(fsys, path); dErr != nil {
return dErr
} else if len(entries) <= 1 {
return nil
}
}
return stopErr
})
if err != nil && err != stopErr {
return "", err
}
return fPath, nil
}