mirror of
https://github.com/wavetermdev/wails.git
synced 2026-08-05 13:53:43 -07:00
[v3, assetServer] Remove fs.FS from options and always use a http.Handler
This commit is contained in:
@@ -17,7 +17,7 @@ func main() {
|
||||
&GreetService{},
|
||||
},
|
||||
Assets: application.AssetOptions{
|
||||
FS: assets,
|
||||
Handler: application.AssetFileServerFS(assets),
|
||||
},
|
||||
Mac: application.MacOptions{
|
||||
ApplicationShouldTerminateAfterLastWindowClosed: true,
|
||||
|
||||
@@ -17,7 +17,7 @@ func main() {
|
||||
Name: "Context Menu Demo",
|
||||
Description: "A demo of the Context Menu API",
|
||||
Assets: application.AssetOptions{
|
||||
FS: assets,
|
||||
Handler: application.AssetFileServerFS(assets),
|
||||
},
|
||||
Mac: application.MacOptions{
|
||||
ApplicationShouldTerminateAfterLastWindowClosed: true,
|
||||
|
||||
@@ -16,7 +16,7 @@ func main() {
|
||||
Name: "dev",
|
||||
Description: "A demo of using raw HTML & CSS",
|
||||
Assets: application.AssetOptions{
|
||||
FS: assets,
|
||||
Handler: application.AssetFileServerFS(assets),
|
||||
},
|
||||
Mac: application.MacOptions{
|
||||
ApplicationShouldTerminateAfterLastWindowClosed: true,
|
||||
|
||||
@@ -18,7 +18,7 @@ func main() {
|
||||
Name: "Drag-n-drop Demo",
|
||||
Description: "A demo of the Drag-n-drop API",
|
||||
Assets: application.AssetOptions{
|
||||
FS: assets,
|
||||
Handler: application.AssetFileServerFS(assets),
|
||||
},
|
||||
Mac: application.MacOptions{
|
||||
ApplicationShouldTerminateAfterLastWindowClosed: true,
|
||||
|
||||
@@ -19,7 +19,7 @@ func main() {
|
||||
Name: "Events Demo",
|
||||
Description: "A demo of the Events API",
|
||||
Assets: application.AssetOptions{
|
||||
FS: assets,
|
||||
Handler: application.AssetFileServerFS(assets),
|
||||
},
|
||||
Mac: application.MacOptions{
|
||||
ApplicationShouldTerminateAfterLastWindowClosed: true,
|
||||
|
||||
@@ -17,7 +17,7 @@ func main() {
|
||||
Name: "Frameless Demo",
|
||||
Description: "A demo of frameless windows",
|
||||
Assets: application.AssetOptions{
|
||||
FS: assets,
|
||||
Handler: application.AssetFileServerFS(assets),
|
||||
},
|
||||
Mac: application.MacOptions{
|
||||
ApplicationShouldTerminateAfterLastWindowClosed: true,
|
||||
|
||||
@@ -3,12 +3,13 @@ package main
|
||||
import (
|
||||
"embed"
|
||||
_ "embed"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/markbates/goth"
|
||||
"github.com/markbates/goth/providers/github"
|
||||
"github.com/wailsapp/wails/v3/pkg/application"
|
||||
"github.com/wailsapp/wails/v3/plugins/oauth"
|
||||
"log"
|
||||
"os"
|
||||
)
|
||||
|
||||
//go:embed assets
|
||||
@@ -34,7 +35,7 @@ func main() {
|
||||
ApplicationShouldTerminateAfterLastWindowClosed: true,
|
||||
},
|
||||
Assets: application.AssetOptions{
|
||||
FS: assets,
|
||||
Handler: application.AssetFileServerFS(assets),
|
||||
},
|
||||
Plugins: map[string]application.Plugin{
|
||||
"github.com/wailsapp/wails/v3/plugins/oauth": oAuthPlugin,
|
||||
|
||||
@@ -46,7 +46,7 @@ func main() {
|
||||
"start_at_login": start_at_login.NewPlugin(start_at_login.Config{}),
|
||||
},
|
||||
Assets: application.AssetOptions{
|
||||
FS: assets,
|
||||
Handler: application.AssetFileServerFS(assets),
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ func main() {
|
||||
WebviewBrowserPath: "",
|
||||
},
|
||||
Assets: application.AssetOptions{
|
||||
FS: assets,
|
||||
Handler: application.AssetFileServerFS(assets),
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ func main() {
|
||||
}),
|
||||
},
|
||||
Assets: application.AssetOptions{
|
||||
FS: assets,
|
||||
Handler: application.AssetFileServerFS(assets),
|
||||
},
|
||||
})
|
||||
go func() {
|
||||
|
||||
@@ -20,7 +20,7 @@ func main() {
|
||||
ApplicationShouldTerminateAfterLastWindowClosed: true,
|
||||
},
|
||||
Assets: application.AssetOptions{
|
||||
FS: assets,
|
||||
Handler: application.AssetFileServerFS(assets),
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
+43
-80
@@ -2,12 +2,13 @@ package assetserver
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"embed"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/fs"
|
||||
iofs "io/fs"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
@@ -18,91 +19,53 @@ const (
|
||||
indexHTML = "index.html"
|
||||
)
|
||||
|
||||
type assetHandler struct {
|
||||
fs iofs.FS
|
||||
handler http.Handler
|
||||
|
||||
logger *slog.Logger
|
||||
|
||||
retryMissingFiles bool
|
||||
type assetFileServer struct {
|
||||
fs iofs.FS
|
||||
err error
|
||||
}
|
||||
|
||||
func NewDefaultAssetHandler(options *Options) (http.Handler, error) {
|
||||
|
||||
vfs := options.Assets
|
||||
if vfs != nil {
|
||||
if _, err := vfs.Open("."); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
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, _ := FindEmbedRootPath(embedFs)
|
||||
msg += fmt.Sprintf(", please make sure the embedded directory '%s' is correct and contains your assets", rootFolder)
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf(msg)
|
||||
func newAssetFileServerFS(vfs fs.FS) http.Handler {
|
||||
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, _ := findEmbedRootPath(embedFs)
|
||||
msg += fmt.Sprintf(", please make sure the embedded directory '%s' is correct and contains your assets", rootFolder)
|
||||
}
|
||||
|
||||
return nil, err
|
||||
err = fmt.Errorf(msg)
|
||||
}
|
||||
|
||||
vfs, err = iofs.Sub(vfs, path.Clean(subDir))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
var result http.Handler = &assetHandler{
|
||||
fs: vfs,
|
||||
handler: options.Handler,
|
||||
logger: options.Logger,
|
||||
}
|
||||
|
||||
if middleware := options.Middleware; middleware != nil {
|
||||
result = middleware(result)
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (d *assetHandler) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
||||
url := req.URL.Path
|
||||
handler := d.handler
|
||||
if strings.EqualFold(req.Method, http.MethodGet) {
|
||||
filename := path.Clean(strings.TrimPrefix(url, "/"))
|
||||
|
||||
d.logInfo("Handling request", "url", url, "file", filename)
|
||||
if err := d.serveFSFile(rw, req, filename); err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
if handler != nil {
|
||||
d.logInfo("File not found. Deferring to AssetHandler", "filename", filename, "url", url)
|
||||
handler.ServeHTTP(rw, req)
|
||||
err = nil
|
||||
} else {
|
||||
rw.WriteHeader(http.StatusNotFound)
|
||||
err = nil
|
||||
}
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
d.logError("Unable to handle request '%s': %s", url, err)
|
||||
http.Error(rw, err.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
} else if handler != nil {
|
||||
d.logInfo("Non-GET request. Deferring to AssetHandler", "url", url)
|
||||
handler.ServeHTTP(rw, req)
|
||||
} else {
|
||||
rw.WriteHeader(http.StatusMethodNotAllowed)
|
||||
vfs, err = iofs.Sub(vfs, path.Clean(subDir))
|
||||
}
|
||||
|
||||
return &assetFileServer{fs: vfs, err: err}
|
||||
}
|
||||
|
||||
func (d *assetFileServer) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
||||
ctx := req.Context()
|
||||
url := req.URL.Path
|
||||
|
||||
err := d.err
|
||||
if err == nil {
|
||||
filename := path.Clean(strings.TrimPrefix(url, "/"))
|
||||
d.logInfo(ctx, "Handling request", "url", url, "file", filename)
|
||||
err = d.serveFSFile(rw, req, filename)
|
||||
if os.IsNotExist(err) {
|
||||
rw.WriteHeader(http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
d.logError(ctx, "Unable to handle request", "url", url, "err", err)
|
||||
http.Error(rw, err.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
|
||||
// serveFile will try to load the file from the fs.FS and write it to the response
|
||||
func (d *assetHandler) serveFSFile(rw http.ResponseWriter, req *http.Request, filename string) error {
|
||||
func (d *assetFileServer) serveFSFile(rw http.ResponseWriter, req *http.Request, filename string) error {
|
||||
if d.fs == nil {
|
||||
return os.ErrNotExist
|
||||
}
|
||||
@@ -182,10 +145,10 @@ func (d *assetHandler) serveFSFile(rw http.ResponseWriter, req *http.Request, fi
|
||||
return err
|
||||
}
|
||||
|
||||
func (d *assetHandler) logInfo(message string, args ...interface{}) {
|
||||
d.logger.Debug("[AssetHandler] "+message, args...)
|
||||
func (d *assetFileServer) logInfo(ctx context.Context, message string, args ...interface{}) {
|
||||
logInfo(ctx, "[AssetFileServerFS] "+message, args...)
|
||||
}
|
||||
|
||||
func (d *assetHandler) logError(message string, args ...interface{}) {
|
||||
d.logger.Error("[AssetHandler] "+message, args...)
|
||||
func (d *assetFileServer) logError(ctx context.Context, message string, args ...interface{}) {
|
||||
logError(ctx, "[AssetFileServerFS] "+message, args...)
|
||||
}
|
||||
@@ -6,7 +6,6 @@ import (
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"net/http/httputil"
|
||||
"net/url"
|
||||
"path"
|
||||
"strings"
|
||||
@@ -29,34 +28,43 @@ type RuntimeHandler interface {
|
||||
type AssetServer struct {
|
||||
options *Options
|
||||
|
||||
handler http.Handler
|
||||
wsHandler *httputil.ReverseProxy
|
||||
handler http.Handler
|
||||
|
||||
pluginScripts map[string]string
|
||||
|
||||
devServerURL string
|
||||
|
||||
assetServerWebView
|
||||
}
|
||||
|
||||
func NewAssetServer(options *Options) (*AssetServer, error) {
|
||||
result := &AssetServer{
|
||||
options: options,
|
||||
result := &AssetServer{options: options}
|
||||
|
||||
userHandler := options.Handler
|
||||
if userHandler == nil {
|
||||
userHandler = http.NotFoundHandler()
|
||||
}
|
||||
|
||||
var err error
|
||||
result.handler, err = result.setupHandler()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
handler := http.Handler(
|
||||
http.HandlerFunc(
|
||||
func(w http.ResponseWriter, r *http.Request) {
|
||||
result.serveHTTP(w, r, userHandler)
|
||||
}))
|
||||
|
||||
if middleware := options.Middleware; middleware != nil {
|
||||
handler = middleware(handler)
|
||||
}
|
||||
|
||||
result.handler = handler
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (a *AssetServer) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
||||
start := time.Now()
|
||||
wrapped := &contentTypeSniffer{rw: rw}
|
||||
a.serveHTTP(wrapped, req)
|
||||
|
||||
req = req.WithContext(contextWithLogger(req.Context(), a.options.Logger))
|
||||
a.handler.ServeHTTP(wrapped, req)
|
||||
|
||||
a.options.Logger.Info(
|
||||
"Asset Request:",
|
||||
"windowName", req.Header.Get(webViewRequestHeaderWindowName),
|
||||
@@ -68,17 +76,11 @@ func (a *AssetServer) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
||||
)
|
||||
}
|
||||
|
||||
func (a *AssetServer) serveHTTP(rw http.ResponseWriter, req *http.Request) {
|
||||
|
||||
if a.wsHandler != nil {
|
||||
a.wsHandler.ServeHTTP(rw, req)
|
||||
func (a *AssetServer) serveHTTP(rw http.ResponseWriter, req *http.Request, userHandler http.Handler) {
|
||||
if isWebSocket(req) {
|
||||
// WebSockets are not supported by the AssetServer
|
||||
rw.WriteHeader(http.StatusNotImplemented)
|
||||
return
|
||||
} else {
|
||||
if isWebSocket(req) {
|
||||
// WebSockets are not supported by the AssetServer
|
||||
rw.WriteHeader(http.StatusNotImplemented)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
header := rw.Header()
|
||||
@@ -91,7 +93,7 @@ func (a *AssetServer) serveHTTP(rw http.ResponseWriter, req *http.Request) {
|
||||
switch path {
|
||||
case "", "/", "/index.html":
|
||||
recorder := httptest.NewRecorder()
|
||||
a.handler.ServeHTTP(recorder, req)
|
||||
userHandler.ServeHTTP(recorder, req)
|
||||
for k, v := range recorder.Result().Header {
|
||||
header[k] = v
|
||||
}
|
||||
@@ -126,7 +128,7 @@ func (a *AssetServer) serveHTTP(rw http.ResponseWriter, req *http.Request) {
|
||||
if script, ok := a.pluginScripts[path]; ok {
|
||||
a.writeBlob(rw, path, []byte(script))
|
||||
} else {
|
||||
a.handler.ServeHTTP(rw, req)
|
||||
userHandler.ServeHTTP(rw, req)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,12 +4,11 @@ package assetserver
|
||||
|
||||
func (a *AssetServer) LogDetails() {
|
||||
var info = []any{
|
||||
"assetsFS", a.options.Assets != nil,
|
||||
"middleware", a.options.Middleware != nil,
|
||||
"handler", a.options.Handler != nil,
|
||||
}
|
||||
if a.devServerURL != "" {
|
||||
info = append(info, "devServerURL", a.devServerURL)
|
||||
if devServerURL := GetDevServerURL(); devServerURL != "" {
|
||||
info = append(info, "devServerURL", devServerURL)
|
||||
}
|
||||
a.options.Logger.Info("AssetServer Info:", info...)
|
||||
}
|
||||
|
||||
@@ -4,8 +4,7 @@ package assetserver
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
"net/url"
|
||||
@@ -19,83 +18,29 @@ func defaultIndexHTML() []byte {
|
||||
return defaultHTML
|
||||
}
|
||||
|
||||
func (a *AssetServer) setupHandler() (http.Handler, error) {
|
||||
|
||||
// Do we have an external dev server URL?
|
||||
a.devServerURL = GetDevServerURL()
|
||||
if a.devServerURL == "" {
|
||||
return NewDefaultAssetHandler(a.options)
|
||||
func NewAssetFileServer(vfs fs.FS) http.Handler {
|
||||
devServerURL := GetDevServerURL()
|
||||
if devServerURL == "" {
|
||||
return newAssetFileServerFS(vfs)
|
||||
}
|
||||
|
||||
// Parse the URL
|
||||
parsedURL, err := url.Parse(a.devServerURL)
|
||||
parsedURL, err := url.Parse(devServerURL)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid FRONTEND_DEVSERVER_URL. Should be valid URL: %s", err.Error())
|
||||
return http.HandlerFunc(
|
||||
func(rw http.ResponseWriter, req *http.Request) {
|
||||
logError(req.Context(), "[ExternalAssetHandler] Invalid FRONTEND_DEVSERVER_URL. Should be valid URL", "error", err.Error())
|
||||
http.Error(rw, err.Error(), http.StatusInternalServerError)
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
baseHandler := a.options.Handler
|
||||
|
||||
errSkipProxy := fmt.Errorf("skip proxying")
|
||||
|
||||
proxy := httputil.NewSingleHostReverseProxy(parsedURL)
|
||||
baseDirector := proxy.Director
|
||||
proxy.Director = func(r *http.Request) {
|
||||
baseDirector(r)
|
||||
if a.options.Logger != nil {
|
||||
a.options.Logger.Debug("ExternalAssetHandler: loading", "url", r.URL)
|
||||
}
|
||||
}
|
||||
|
||||
proxy.ModifyResponse = func(res *http.Response) error {
|
||||
if baseHandler == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if res.StatusCode == http.StatusSwitchingProtocols {
|
||||
return nil
|
||||
}
|
||||
|
||||
if res.StatusCode == http.StatusNotFound || res.StatusCode == http.StatusMethodNotAllowed {
|
||||
return errSkipProxy
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
proxy.ErrorHandler = func(rw http.ResponseWriter, r *http.Request, err error) {
|
||||
if baseHandler != nil && errors.Is(err, errSkipProxy) {
|
||||
if a.options.Logger != nil {
|
||||
a.options.Logger.Debug("ExternalAssetHandler: Loading file failed, using original AssetHandler", "url", r.URL)
|
||||
}
|
||||
baseHandler.ServeHTTP(rw, r)
|
||||
} else {
|
||||
if a.options.Logger != nil {
|
||||
a.options.Logger.Error("ExternalAssetHandler: Proxy error", "error", err.Error())
|
||||
}
|
||||
rw.WriteHeader(http.StatusBadGateway)
|
||||
}
|
||||
logError(r.Context(), "[ExternalAssetHandler] Proxy error", "error", err.Error())
|
||||
rw.WriteHeader(http.StatusBadGateway)
|
||||
}
|
||||
|
||||
var result http.Handler = http.HandlerFunc(
|
||||
func(rw http.ResponseWriter, req *http.Request) {
|
||||
if req.Method == http.MethodGet {
|
||||
proxy.ServeHTTP(rw, req)
|
||||
return
|
||||
}
|
||||
|
||||
if baseHandler != nil {
|
||||
baseHandler.ServeHTTP(rw, req)
|
||||
return
|
||||
}
|
||||
|
||||
rw.WriteHeader(http.StatusMethodNotAllowed)
|
||||
})
|
||||
|
||||
if middleware := a.options.Middleware; middleware != nil {
|
||||
result = middleware(result)
|
||||
}
|
||||
|
||||
return result, nil
|
||||
return proxy
|
||||
}
|
||||
|
||||
func GetDevServerURL() string {
|
||||
|
||||
@@ -2,14 +2,17 @@
|
||||
|
||||
package assetserver
|
||||
|
||||
import "net/http"
|
||||
import (
|
||||
"io/fs"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func defaultIndexHTML() []byte {
|
||||
return []byte{}
|
||||
}
|
||||
|
||||
func (a *AssetServer) setupHandler() (http.Handler, error) {
|
||||
return NewDefaultAssetHandler(a.options)
|
||||
func NewAssetFileServer(vfs fs.FS) http.Handler {
|
||||
return newAssetFileServerFS(vfs)
|
||||
}
|
||||
|
||||
func GetDevServerURL() string {
|
||||
|
||||
@@ -2,8 +2,10 @@ package assetserver
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
@@ -20,6 +22,10 @@ const (
|
||||
WailsUserAgentValue = "wails.io"
|
||||
)
|
||||
|
||||
var (
|
||||
assetServerLogger = struct{}{}
|
||||
)
|
||||
|
||||
func serveFile(rw http.ResponseWriter, filename string, blob []byte) error {
|
||||
header := rw.Header()
|
||||
header.Set(HeaderContentLength, fmt.Sprintf("%d", len(blob)))
|
||||
@@ -37,3 +43,19 @@ func isWebSocket(req *http.Request) bool {
|
||||
upgrade := req.Header.Get(HeaderUpgrade)
|
||||
return strings.EqualFold(upgrade, "websocket")
|
||||
}
|
||||
|
||||
func contextWithLogger(ctx context.Context, logger *slog.Logger) context.Context {
|
||||
return context.WithValue(ctx, assetServerLogger, logger)
|
||||
}
|
||||
|
||||
func logInfo(ctx context.Context, message string, args ...interface{}) {
|
||||
if logger, _ := ctx.Value(assetServerLogger).(*slog.Logger); logger != nil {
|
||||
logger.Info(message, args...)
|
||||
}
|
||||
}
|
||||
|
||||
func logError(ctx context.Context, message string, args ...interface{}) {
|
||||
if logger, _ := ctx.Value(assetServerLogger).(*slog.Logger); logger != nil {
|
||||
logger.Error(message, args...)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,8 +10,8 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// FindEmbedRootPath finds the root path in the embed FS. It's the directory which contains all the files.
|
||||
func FindEmbedRootPath(fileSystem embed.FS) (string, error) {
|
||||
// findEmbedRootPath finds the root path in the embed FS. It's the directory which contains all the files.
|
||||
func findEmbedRootPath(fileSystem embed.FS) (string, error) {
|
||||
stopErr := fmt.Errorf("files or multiple dirs found")
|
||||
|
||||
fPath := ""
|
||||
@@ -39,7 +39,7 @@ func FindEmbedRootPath(fileSystem embed.FS) (string, error) {
|
||||
return fPath, nil
|
||||
}
|
||||
|
||||
func FindPathToFile(fileSystem fs.FS, file string) (string, error) {
|
||||
func findPathToFile(fileSystem fs.FS, file string) (string, error) {
|
||||
stat, _ := fs.Stat(fileSystem, file)
|
||||
if stat != nil {
|
||||
return ".", nil
|
||||
|
||||
@@ -2,26 +2,13 @@ package assetserver
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// Options defines the configuration of the AssetServer.
|
||||
type Options struct {
|
||||
// Assets defines the static assets to be used. A GET request is first tried to be served from this Assets. If the Assets returns
|
||||
// `os.ErrNotExist` for that file, the request handling will fallback to the Handler and tries to serve the GET
|
||||
// request from it.
|
||||
//
|
||||
// If set to nil, all GET requests will be forwarded to Handler.
|
||||
Assets fs.FS
|
||||
|
||||
// Handler will be called for every GET request that can't be served from Assets, due to `os.ErrNotExist`. Furthermore all
|
||||
// non GET requests will always be served from this Handler.
|
||||
//
|
||||
// If not defined, the result is the following in cases where the Handler would have been called:
|
||||
// GET request: `http.StatusNotFound`
|
||||
// Other request: `http.StatusMethodNotAllowed`
|
||||
// Handler which serves all the content to the WebView.
|
||||
Handler http.Handler
|
||||
|
||||
// Middleware is a HTTP Middleware which allows to hook into the AssetServer request chain. It allows to skip the default
|
||||
@@ -29,6 +16,8 @@ type Options struct {
|
||||
// The Middleware is called to build a new `http.Handler` used by the AssetSever and it also receives the default
|
||||
// handler used by the AssetServer as an argument.
|
||||
//
|
||||
// This middleware injects itself before any of Wails internal middlewares.
|
||||
//
|
||||
// If not defined, the default AssetServer request chain is executed.
|
||||
//
|
||||
// Multiple Middlewares can be chained together with:
|
||||
@@ -50,8 +39,8 @@ type Options struct {
|
||||
|
||||
// Validate the options
|
||||
func (o Options) Validate() error {
|
||||
if o.Assets == nil && o.Handler == nil && o.Middleware == nil {
|
||||
return fmt.Errorf("AssetServer options invalid: either Assets, Handler or Middleware must be set")
|
||||
if o.Handler == nil && o.Middleware == nil {
|
||||
return fmt.Errorf("AssetServer options invalid: either Handler or Middleware must be set")
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -3,9 +3,6 @@ package application
|
||||
import (
|
||||
"embed"
|
||||
"encoding/json"
|
||||
"github.com/pkg/browser"
|
||||
"github.com/samber/lo"
|
||||
"github.com/wailsapp/wails/v3/internal/signal"
|
||||
"io"
|
||||
"log"
|
||||
"log/slog"
|
||||
@@ -15,6 +12,10 @@ import (
|
||||
"strconv"
|
||||
"sync"
|
||||
|
||||
"github.com/pkg/browser"
|
||||
"github.com/samber/lo"
|
||||
"github.com/wailsapp/wails/v3/internal/signal"
|
||||
|
||||
"github.com/wailsapp/wails/v3/internal/assetserver"
|
||||
"github.com/wailsapp/wails/v3/internal/assetserver/webview"
|
||||
"github.com/wailsapp/wails/v3/internal/capabilities"
|
||||
@@ -29,7 +30,7 @@ var globalApplication *App
|
||||
|
||||
// AlphaAssets is the default assets for the alpha application
|
||||
var AlphaAssets = AssetOptions{
|
||||
FS: alphaAssets,
|
||||
Handler: AssetFileServerFS(alphaAssets),
|
||||
}
|
||||
|
||||
func init() {
|
||||
@@ -76,7 +77,6 @@ func New(appOptions Options) *App {
|
||||
result.Events = NewWailsEventProcessor(result.dispatchEventToWindows)
|
||||
|
||||
opts := &assetserver.Options{
|
||||
Assets: appOptions.Assets.FS,
|
||||
Handler: appOptions.Assets.Handler,
|
||||
Middleware: assetserver.Middleware(appOptions.Assets.Middleware),
|
||||
Logger: result.Logger,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user