mirror of
https://github.com/wailsapp/wails.git
synced 2025-05-02 22:13:36 +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:
parent
66bc258f81
commit
d3b4105f75
@ -2,7 +2,6 @@ package assetserver
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"embed"
|
||||
"errors"
|
||||
"fmt"
|
||||
@ -13,11 +12,14 @@ import (
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"github.com/wailsapp/wails/v2/internal/fs"
|
||||
"github.com/wailsapp/wails/v2/internal/logger"
|
||||
"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
|
||||
var defaultHTML []byte
|
||||
|
||||
@ -29,16 +31,12 @@ type assetHandler struct {
|
||||
fs iofs.FS
|
||||
handler http.Handler
|
||||
|
||||
logger *logger.Logger
|
||||
logger Logger
|
||||
|
||||
retryMissingFiles bool
|
||||
}
|
||||
|
||||
func NewAssetHandler(ctx context.Context, options assetserver.Options) (http.Handler, error) {
|
||||
var log *logger.Logger
|
||||
if _logger := ctx.Value("logger"); _logger != nil {
|
||||
log = _logger.(*logger.Logger)
|
||||
}
|
||||
func NewAssetHandler(options assetserver.Options, log Logger) (http.Handler, error) {
|
||||
|
||||
vfs := options.Assets
|
||||
if vfs != nil {
|
||||
@ -46,12 +44,12 @@ func NewAssetHandler(ctx context.Context, options assetserver.Options) (http.Han
|
||||
return nil, err
|
||||
}
|
||||
|
||||
subDir, err := fs.FindPathToFile(vfs, indexHTML)
|
||||
subDir, err := FindPathToFile(vfs, indexHTML)
|
||||
if err != nil {
|
||||
if errors.Is(err, os.ErrNotExist) {
|
||||
msg := "no `index.html` could be found in your Assets fs.FS"
|
||||
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)
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,6 @@ package assetserver
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
@ -10,8 +9,6 @@ import (
|
||||
|
||||
"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/assetserver"
|
||||
)
|
||||
@ -21,41 +18,48 @@ const (
|
||||
ipcJSPath = "/wails/ipc.js"
|
||||
)
|
||||
|
||||
type RuntimeAssets interface {
|
||||
DesktopIPC() []byte
|
||||
WebsocketIPC() []byte
|
||||
RuntimeDesktopJS() []byte
|
||||
}
|
||||
|
||||
type AssetServer struct {
|
||||
handler http.Handler
|
||||
wsHandler http.Handler
|
||||
runtimeJS []byte
|
||||
ipcJS func(*http.Request) []byte
|
||||
|
||||
logger *logger.Logger
|
||||
logger Logger
|
||||
runtime RuntimeAssets
|
||||
|
||||
servingFromDisk 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)
|
||||
if err != nil {
|
||||
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) {
|
||||
handler, err := NewAssetHandler(ctx, options)
|
||||
func NewAssetServer(bindingsJSON string, options assetserver.Options, servingFromDisk bool, logger Logger, runtime RuntimeAssets) (*AssetServer, error) {
|
||||
handler, err := NewAssetHandler(options, logger)
|
||||
if err != nil {
|
||||
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
|
||||
if bindingsJSON != "" {
|
||||
buffer.WriteString(`window.wailsbindings='` + bindingsJSON + `';` + "\n")
|
||||
}
|
||||
buffer.Write(runtime.RuntimeDesktopJS)
|
||||
buffer.Write(runtime.RuntimeDesktopJS())
|
||||
|
||||
result := &AssetServer{
|
||||
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.
|
||||
// We indicate this through the `servingFromDisk` flag to ensure requests
|
||||
// aren't cached in dev mode.
|
||||
servingFromDisk: ctx.Value("assetdir") != nil,
|
||||
}
|
||||
|
||||
if _logger := ctx.Value("logger"); _logger != nil {
|
||||
result.logger = _logger.(*logger.Logger)
|
||||
servingFromDisk: servingFromDisk,
|
||||
logger: logger,
|
||||
runtime: runtime,
|
||||
}
|
||||
|
||||
return result, nil
|
||||
@ -121,7 +123,7 @@ func (d *AssetServer) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
||||
d.writeBlob(rw, path, d.runtimeJS)
|
||||
|
||||
case ipcJSPath:
|
||||
content := runtime.DesktopIPC
|
||||
content := d.runtime.DesktopIPC()
|
||||
if d.ipcJS != nil {
|
||||
content = d.ipcJS(req)
|
||||
}
|
||||
|
@ -4,11 +4,8 @@
|
||||
package assetserver
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"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
|
||||
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) {
|
||||
result, err := NewAssetServerWithHandler(ctx, handler, bindingsJSON)
|
||||
func NewDevAssetServer(handler http.Handler, wsHandler http.Handler, bindingsJSON string, servingFromDisk bool, logger Logger, runtime RuntimeAssets) (*AssetServer, error) {
|
||||
result, err := NewAssetServerWithHandler(handler, bindingsJSON, servingFromDisk, logger, runtime)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -26,9 +23,9 @@ func NewDevAssetServer(ctx context.Context, handler http.Handler, wsHandler http
|
||||
result.appendSpinnerToBody = true
|
||||
result.ipcJS = func(req *http.Request) []byte {
|
||||
if strings.Contains(req.UserAgent(), WailsUserAgentValue) {
|
||||
return runtime.DesktopIPC
|
||||
return runtime.DesktopIPC()
|
||||
}
|
||||
return runtime.WebsocketIPC
|
||||
return runtime.WebsocketIPC()
|
||||
}
|
||||
|
||||
return result, nil
|
||||
|
75
v2/internal/frontend/assetserver/fs.go
Normal file
75
v2/internal/frontend/assetserver/fs.go
Normal 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)
|
||||
}
|
@ -26,6 +26,7 @@ import (
|
||||
"github.com/wailsapp/wails/v2/internal/binding"
|
||||
"github.com/wailsapp/wails/v2/internal/frontend"
|
||||
"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/pkg/options"
|
||||
)
|
||||
@ -86,7 +87,8 @@ func NewFrontend(ctx context.Context, appoptions *options.App, myLogger *logger.
|
||||
} else {
|
||||
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 {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
@ -91,6 +91,7 @@ import (
|
||||
"github.com/wailsapp/wails/v2/internal/binding"
|
||||
"github.com/wailsapp/wails/v2/internal/frontend"
|
||||
"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/pkg/options"
|
||||
)
|
||||
@ -159,7 +160,7 @@ func NewFrontend(ctx context.Context, appoptions *options.App, myLogger *logger.
|
||||
} else {
|
||||
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 {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ import (
|
||||
"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/w32"
|
||||
wailsruntime "github.com/wailsapp/wails/v2/internal/frontend/runtime"
|
||||
"github.com/wailsapp/wails/v2/internal/logger"
|
||||
"github.com/wailsapp/wails/v2/internal/system/operatingsystem"
|
||||
"github.com/wailsapp/wails/v2/pkg/options"
|
||||
@ -102,7 +103,7 @@ func NewFrontend(ctx context.Context, appoptions *options.App, myLogger *logger.
|
||||
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 {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
@ -18,6 +18,8 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/wailsapp/wails/v2/internal/frontend/runtime"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/wailsapp/wails/v2/internal/binding"
|
||||
"github.com/wailsapp/wails/v2/internal/frontend"
|
||||
@ -61,6 +63,8 @@ func (d *DevWebServer) Run(ctx context.Context) error {
|
||||
|
||||
var assetHandler http.Handler
|
||||
var wsHandler http.Handler
|
||||
var myLogger *logger.Logger
|
||||
|
||||
_fronendDevServerURL, _ := ctx.Value("frontenddevserverurl").(string)
|
||||
if _fronendDevServerURL == "" {
|
||||
assetdir, _ := ctx.Value("assetdir").(string)
|
||||
@ -68,8 +72,11 @@ func (d *DevWebServer) Run(ctx context.Context) error {
|
||||
return c.String(http.StatusOK, assetdir)
|
||||
})
|
||||
|
||||
if _logger := ctx.Value("logger"); _logger != nil {
|
||||
myLogger = _logger.(*logger.Logger)
|
||||
}
|
||||
var err error
|
||||
assetHandler, err = assetserver.NewAssetHandler(ctx, assetServerConfig)
|
||||
assetHandler, err = assetserver.NewAssetHandler(assetServerConfig, myLogger)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
@ -101,7 +108,7 @@ func (d *DevWebServer) Run(ctx context.Context) error {
|
||||
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 {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
26
v2/internal/frontend/runtime/assets.go
Normal file
26
v2/internal/frontend/runtime/assets.go
Normal 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
|
||||
}
|
27
v2/internal/frontend/runtime/assets_dev.go
Normal file
27
v2/internal/frontend/runtime/assets_dev.go
Normal 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
|
||||
}
|
@ -2,7 +2,6 @@ package fs
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"embed"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/fs"
|
||||
@ -403,32 +402,3 @@ func FindFileInParents(path string, filename string) string {
|
||||
}
|
||||
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
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user