diff --git a/v2/cmd/wails/internal/commands/generate/template/base/main.go.tmpl b/v2/cmd/wails/internal/commands/generate/template/base/main.go.tmpl
index 268a44348..d8e902027 100644
--- a/v2/cmd/wails/internal/commands/generate/template/base/main.go.tmpl
+++ b/v2/cmd/wails/internal/commands/generate/template/base/main.go.tmpl
@@ -7,6 +7,7 @@ import (
"github.com/wailsapp/wails/v2"
"github.com/wailsapp/wails/v2/pkg/logger"
"github.com/wailsapp/wails/v2/pkg/options"
+ "github.com/wailsapp/wails/v2/pkg/options/assetserver"
"github.com/wailsapp/wails/v2/pkg/options/mac"
"github.com/wailsapp/wails/v2/pkg/options/windows"
)
@@ -36,7 +37,9 @@ func main() {
StartHidden: false,
HideWindowOnClose: false,
BackgroundColour: &options.RGBA{R: 255, G: 255, B: 255, A: 255},
- Assets: assets,
+ AssetServer: &assetserver.Options{
+ Assets: assets,
+ },
Menu: nil,
Logger: nil,
LogLevel: logger.DEBUG,
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/generate/plain/main.go.tmpl b/v2/cmd/wails/internal/commands/initialise/templates/generate/plain/main.go.tmpl
index 8f37a961a..433cfee4e 100644
--- a/v2/cmd/wails/internal/commands/initialise/templates/generate/plain/main.go.tmpl
+++ b/v2/cmd/wails/internal/commands/initialise/templates/generate/plain/main.go.tmpl
@@ -9,6 +9,7 @@ import (
"github.com/wailsapp/wails/v2"
"github.com/wailsapp/wails/v2/pkg/logger"
"github.com/wailsapp/wails/v2/pkg/options"
+ "github.com/wailsapp/wails/v2/pkg/options/assetserver"
"github.com/wailsapp/wails/v2/pkg/options/windows"
)
@@ -37,7 +38,9 @@ func main() {
StartHidden: false,
HideWindowOnClose: false,
BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1},
- Assets: assets,
+ AssetServer: &assetserver.Options{
+ Assets: assets,
+ },
Menu: nil,
Logger: nil,
LogLevel: logger.DEBUG,
diff --git a/v2/cmd/wails/internal/commands/initialise/templates/templates/vue/main.tmpl.go b/v2/cmd/wails/internal/commands/initialise/templates/templates/vue/main.tmpl.go
index e0f197dee..e24782be3 100644
--- a/v2/cmd/wails/internal/commands/initialise/templates/templates/vue/main.tmpl.go
+++ b/v2/cmd/wails/internal/commands/initialise/templates/templates/vue/main.tmpl.go
@@ -5,6 +5,7 @@ import (
"github.com/wailsapp/wails/v2"
"github.com/wailsapp/wails/v2/pkg/options"
+ "github.com/wailsapp/wails/v2/pkg/options/assetserver"
)
//go:embed all:frontend/dist
@@ -16,10 +17,12 @@ func main() {
// Create application with options
err := wails.Run(&options.App{
- Title: "{{.ProjectName}}",
- Width: 1024,
- Height: 768,
- Assets: assets,
+ Title: "{{.ProjectName}}",
+ Width: 1024,
+ Height: 768,
+ AssetServer: &assetserver.Options{
+ Assets: assets,
+ },
BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1},
OnStartup: app.startup,
Bind: []interface{}{
diff --git a/v2/internal/app/app_dev.go b/v2/internal/app/app_dev.go
index d807ed9a3..35c02678f 100644
--- a/v2/internal/app/app_dev.go
+++ b/v2/internal/app/app_dev.go
@@ -13,6 +13,7 @@ import (
"path/filepath"
"github.com/wailsapp/wails/v2/internal/binding"
+ "github.com/wailsapp/wails/v2/internal/frontend/assetserver"
"github.com/wailsapp/wails/v2/internal/frontend/desktop"
"github.com/wailsapp/wails/v2/internal/frontend/devserver"
"github.com/wailsapp/wails/v2/internal/frontend/dispatcher"
@@ -90,6 +91,14 @@ func CreateApp(appoptions *options.App) (*App, error) {
}
}
+ assetConfig := assetserver.BuildAssetServerConfig(appoptions)
+
+ if assetConfig.Assets == nil && frontendDevServerURL != "" {
+ myLogger.Warning("No AssetServer.Assets has been defined but a frontend DevServer, the frontend DevServer will not be used.")
+ frontendDevServerURL = ""
+ assetdir = ""
+ }
+
if frontendDevServerURL != "" {
if devServer == "" {
return nil, fmt.Errorf("Unable to use FrontendDevServerUrl without a DevServer address")
@@ -107,7 +116,7 @@ func CreateApp(appoptions *options.App) (*App, error) {
} else {
if assetdir == "" {
// If no assetdir has been defined, let's try to infer it from the project root and the asset FS.
- assetdir, err = tryInferAssetDirFromFS(appoptions.Assets)
+ assetdir, err = tryInferAssetDirFromFS(assetConfig.Assets)
if err != nil {
return nil, err
}
@@ -121,12 +130,17 @@ func CreateApp(appoptions *options.App) (*App, error) {
}
myLogger.Info("Serving assets from disk: %s", absdir)
- appoptions.Assets = os.DirFS(absdir)
+ assetConfig.Assets = os.DirFS(absdir)
ctx = context.WithValue(ctx, "assetdir", assetdir)
}
}
+ // Migrate deprecated options to the new AssetServer option
+ appoptions.Assets = nil
+ appoptions.AssetsHandler = nil
+ appoptions.AssetServer = &assetConfig
+
if devServer != "" {
ctx = context.WithValue(ctx, "devserver", devServer)
}
diff --git a/v2/internal/frontend/assetserver/assethandler.go b/v2/internal/frontend/assetserver/assethandler.go
index ca73be4d2..09353aa3f 100644
--- a/v2/internal/frontend/assetserver/assethandler.go
+++ b/v2/internal/frontend/assetserver/assethandler.go
@@ -14,6 +14,7 @@ import (
"github.com/wailsapp/wails/v2/internal/fs"
"github.com/wailsapp/wails/v2/internal/logger"
+ "github.com/wailsapp/wails/v2/pkg/options/assetserver"
)
//go:embed defaultindex.html
@@ -32,7 +33,13 @@ type assetHandler struct {
retryMissingFiles bool
}
-func NewAssetHandler(ctx context.Context, vfs iofs.FS, assetsHandler http.Handler) (http.Handler, error) {
+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)
+ }
+
+ vfs := options.Assets
if vfs != nil {
if _, err := vfs.Open("."); err != nil {
return nil, err
@@ -49,13 +56,14 @@ func NewAssetHandler(ctx context.Context, vfs iofs.FS, assetsHandler http.Handle
}
}
- result := &assetHandler{
+ var result http.Handler = &assetHandler{
fs: vfs,
- handler: assetsHandler,
+ handler: options.Handler,
+ logger: log,
}
- if _logger := ctx.Value("logger"); _logger != nil {
- result.logger = _logger.(*logger.Logger)
+ if middleware := options.Middleware; middleware != nil {
+ result = middleware(result)
}
return result, nil
diff --git a/v2/internal/frontend/assetserver/assetserver.go b/v2/internal/frontend/assetserver/assetserver.go
index 5fff282f2..fd66d46bd 100644
--- a/v2/internal/frontend/assetserver/assetserver.go
+++ b/v2/internal/frontend/assetserver/assetserver.go
@@ -4,15 +4,16 @@ import (
"bytes"
"context"
"fmt"
- iofs "io/fs"
"net/http"
"net/http/httptest"
"strconv"
+ "golang.org/x/net/html"
+
"github.com/wailsapp/wails/v2/internal/frontend/runtime"
"github.com/wailsapp/wails/v2/internal/logger"
-
- "golang.org/x/net/html"
+ "github.com/wailsapp/wails/v2/pkg/options"
+ "github.com/wailsapp/wails/v2/pkg/options/assetserver"
)
const (
@@ -22,6 +23,7 @@ const (
type AssetServer struct {
handler http.Handler
+ wsHandler http.Handler
runtimeJS []byte
ipcJS func(*http.Request) []byte
@@ -31,8 +33,12 @@ type AssetServer struct {
appendSpinnerToBody bool
}
-func NewAssetServer(ctx context.Context, vfs iofs.FS, assetsHandler http.Handler, bindingsJSON string) (*AssetServer, error) {
- handler, err := NewAssetHandler(ctx, vfs, assetsHandler)
+func NewAssetServerMainPage(ctx context.Context, bindingsJSON string, options *options.App) (*AssetServer, error) {
+ return NewAssetServer(ctx, bindingsJSON, BuildAssetServerConfig(options))
+}
+
+func NewAssetServer(ctx context.Context, bindingsJSON string, options assetserver.Options) (*AssetServer, error) {
+ handler, err := NewAssetHandler(ctx, options)
if err != nil {
return nil, err
}
@@ -66,17 +72,21 @@ func NewAssetServerWithHandler(ctx context.Context, handler http.Handler, bindin
}
func (d *AssetServer) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
+ if isWebSocket(req) {
+ // Forward WebSockets to the distinct websocket handler if it exists
+ if wsHandler := d.wsHandler; wsHandler != nil {
+ wsHandler.ServeHTTP(rw, req)
+ } else {
+ rw.WriteHeader(http.StatusNotImplemented)
+ }
+ return
+ }
+
header := rw.Header()
if d.servingFromDisk {
header.Add(HeaderCacheControl, "no-cache")
}
- if isWebSocket(req) {
- // WebSockets can always directly be forwarded to the handler
- d.handler.ServeHTTP(rw, req)
- return
- }
-
path := req.URL.Path
switch path {
case "", "/", "/index.html":
diff --git a/v2/internal/frontend/assetserver/assetserver_browser_dev.go b/v2/internal/frontend/assetserver/assetserver_dev.go
similarity index 56%
rename from v2/internal/frontend/assetserver/assetserver_browser_dev.go
rename to v2/internal/frontend/assetserver/assetserver_dev.go
index 6ced11787..5d83cf5fe 100644
--- a/v2/internal/frontend/assetserver/assetserver_browser_dev.go
+++ b/v2/internal/frontend/assetserver/assetserver_dev.go
@@ -12,15 +12,17 @@ import (
)
/*
-The assetserver for dev serves assets from disk.
-It injects a websocket based IPC script into `index.html`.
+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 NewBrowserAssetServer(ctx context.Context, handler http.Handler, bindingsJSON string) (*AssetServer, error) {
+func NewDevAssetServer(ctx context.Context, handler http.Handler, wsHandler http.Handler, bindingsJSON string) (*AssetServer, error) {
result, err := NewAssetServerWithHandler(ctx, handler, bindingsJSON)
if err != nil {
return nil, err
}
+ result.wsHandler = wsHandler
result.appendSpinnerToBody = true
result.ipcJS = func(req *http.Request) []byte {
if strings.Contains(req.UserAgent(), WailsUserAgentValue) {
diff --git a/v2/internal/frontend/assetserver/common.go b/v2/internal/frontend/assetserver/common.go
index b787cc6bb..ffe80577a 100644
--- a/v2/internal/frontend/assetserver/common.go
+++ b/v2/internal/frontend/assetserver/common.go
@@ -8,9 +8,26 @@ import (
"net/http"
"strings"
+ "github.com/wailsapp/wails/v2/pkg/options"
+ "github.com/wailsapp/wails/v2/pkg/options/assetserver"
"golang.org/x/net/html"
)
+func BuildAssetServerConfig(options *options.App) assetserver.Options {
+ if opts := options.AssetServer; opts != nil {
+ if options.Assets != nil || options.AssetsHandler != nil {
+ panic("It's not possible to use the deprecated Assets and AssetsHandler options and the new AssetServer option at the same time. Please migrate all your Assets options to the AssetServer option.")
+ }
+
+ return *opts
+ }
+
+ return assetserver.Options{
+ Assets: options.Assets,
+ Handler: options.AssetsHandler,
+ }
+}
+
const (
HeaderHost = "Host"
HeaderContentType = "Content-Type"
diff --git a/v2/internal/frontend/desktop/darwin/frontend.go b/v2/internal/frontend/desktop/darwin/frontend.go
index ca9975749..a1eff8e8d 100644
--- a/v2/internal/frontend/desktop/darwin/frontend.go
+++ b/v2/internal/frontend/desktop/darwin/frontend.go
@@ -90,7 +90,7 @@ func NewFrontend(ctx context.Context, appoptions *options.App, myLogger *logger.
} else {
appBindings.DB().UpdateObfuscatedCallMap()
}
- assets, err := assetserver.NewAssetServer(ctx, appoptions.Assets, appoptions.AssetsHandler, bindings)
+ assets, err := assetserver.NewAssetServerMainPage(ctx, bindings, appoptions)
if err != nil {
log.Fatal(err)
}
diff --git a/v2/internal/frontend/desktop/linux/frontend.go b/v2/internal/frontend/desktop/linux/frontend.go
index 6457bc984..bb934d343 100644
--- a/v2/internal/frontend/desktop/linux/frontend.go
+++ b/v2/internal/frontend/desktop/linux/frontend.go
@@ -94,7 +94,7 @@ func NewFrontend(ctx context.Context, appoptions *options.App, myLogger *logger.
} else {
appBindings.DB().UpdateObfuscatedCallMap()
}
- assets, err := assetserver.NewAssetServer(ctx, appoptions.Assets, appoptions.AssetsHandler, bindings)
+ assets, err := assetserver.NewAssetServerMainPage(ctx, bindings, appoptions)
if err != nil {
log.Fatal(err)
}
diff --git a/v2/internal/frontend/desktop/windows/frontend.go b/v2/internal/frontend/desktop/windows/frontend.go
index 7135f5d03..f5eb3b92d 100644
--- a/v2/internal/frontend/desktop/windows/frontend.go
+++ b/v2/internal/frontend/desktop/windows/frontend.go
@@ -102,7 +102,7 @@ func NewFrontend(ctx context.Context, appoptions *options.App, myLogger *logger.
appBindings.DB().UpdateObfuscatedCallMap()
}
- assets, err := assetserver.NewAssetServer(ctx, appoptions.Assets, appoptions.AssetsHandler, bindings)
+ assets, err := assetserver.NewAssetServerMainPage(ctx, bindings, appoptions)
if err != nil {
log.Fatal(err)
}
@@ -435,9 +435,8 @@ func (f *Frontend) setupChromium() {
log.Fatal(err)
}
-
- if opts := f.frontendOptions.Windows; opts != nil {
- if opts.ZoomFactor > 0.0 {
+ if opts := f.frontendOptions.Windows; opts != nil {
+ if opts.ZoomFactor > 0.0 {
chromium.PutZoomFactor(opts.ZoomFactor)
}
err = settings.PutIsZoomControlEnabled(opts.IsZoomControlEnabled)
diff --git a/v2/internal/frontend/devserver/devserver.go b/v2/internal/frontend/devserver/devserver.go
index 3cfebd587..6dc18b8e0 100644
--- a/v2/internal/frontend/devserver/devserver.go
+++ b/v2/internal/frontend/devserver/devserver.go
@@ -12,6 +12,7 @@ import (
"log"
"net"
"net/http"
+ "net/http/httputil"
"net/url"
"strings"
"sync"
@@ -53,7 +54,10 @@ func (d *DevWebServer) Run(ctx context.Context) error {
d.server.GET("/wails/reload", d.handleReload)
d.server.GET("/wails/ipc", d.handleIPCWebSocket)
+ assetServerConfig := assetserver.BuildAssetServerConfig(d.appoptions)
+
var assetHandler http.Handler
+ var wsHandler http.Handler
_fronendDevServerURL, _ := ctx.Value("frontenddevserverurl").(string)
if _fronendDevServerURL == "" {
assetdir, _ := ctx.Value("assetdir").(string)
@@ -62,7 +66,7 @@ func (d *DevWebServer) Run(ctx context.Context) error {
})
var err error
- assetHandler, err = assetserver.NewAssetHandler(ctx, d.appoptions.Assets, d.appoptions.AssetsHandler)
+ assetHandler, err = assetserver.NewAssetHandler(ctx, assetServerConfig)
if err != nil {
log.Fatal(err)
}
@@ -81,7 +85,11 @@ func (d *DevWebServer) Run(ctx context.Context) error {
d.logger.Error("Timeout waiting for frontend DevServer")
}
- assetHandler = newExternalDevServerAssetHandler(d.logger, externalURL, d.appoptions.AssetsHandler)
+ assetHandler = newExternalDevServerAssetHandler(d.logger, externalURL, assetServerConfig)
+ // WebSockets aren't currently supported in prod mode, so a WebSocket connection is the result of the
+ // FrontendDevServer e.g. Vite to support auto reloads.
+ // Therefore we direct WebSockets directly to the FrontendDevServer instead of returning a NotImplementedStatus.
+ wsHandler = httputil.NewSingleHostReverseProxy(externalURL)
}
// Setup internal dev server
@@ -90,7 +98,7 @@ func (d *DevWebServer) Run(ctx context.Context) error {
log.Fatal(err)
}
- assetServer, err := assetserver.NewBrowserAssetServer(ctx, assetHandler, bindingsJSON)
+ assetServer, err := assetserver.NewDevAssetServer(ctx, assetHandler, wsHandler, bindingsJSON)
if err != nil {
log.Fatal(err)
}
diff --git a/v2/internal/frontend/devserver/external.go b/v2/internal/frontend/devserver/external.go
index a07b1c0d6..fd717e723 100644
--- a/v2/internal/frontend/devserver/external.go
+++ b/v2/internal/frontend/devserver/external.go
@@ -10,11 +10,21 @@ import (
"net/http/httputil"
"net/url"
- "github.com/labstack/echo/v4"
"github.com/wailsapp/wails/v2/internal/logger"
+ "github.com/wailsapp/wails/v2/pkg/options/assetserver"
)
-func newExternalDevServerAssetHandler(logger *logger.Logger, url *url.URL, handler http.Handler) http.Handler {
+func newExternalDevServerAssetHandler(logger *logger.Logger, url *url.URL, options assetserver.Options) http.Handler {
+ handler := newExternalAssetsHandler(logger, url, options.Handler)
+
+ if middleware := options.Middleware; middleware != nil {
+ handler = middleware(handler)
+ }
+
+ return handler
+}
+
+func newExternalAssetsHandler(logger *logger.Logger, url *url.URL, handler http.Handler) http.Handler {
errSkipProxy := fmt.Errorf("skip proxying")
proxy := httputil.NewSingleHostReverseProxy(url)
@@ -56,23 +66,18 @@ func newExternalDevServerAssetHandler(logger *logger.Logger, url *url.URL, handl
}
}
- e := echo.New()
- e.Any("/*",
- func(c echo.Context) error {
- req := c.Request()
- rw := c.Response()
- if c.IsWebSocket() || req.Method == http.MethodGet {
+ return http.HandlerFunc(
+ func(rw http.ResponseWriter, req *http.Request) {
+ if req.Method == http.MethodGet {
proxy.ServeHTTP(rw, req)
- return nil
+ return
}
if handler != nil {
handler.ServeHTTP(rw, req)
- return nil
+ return
}
- return c.NoContent(http.StatusMethodNotAllowed)
+ rw.WriteHeader(http.StatusMethodNotAllowed)
})
-
- return e
}
diff --git a/v2/internal/staticanalysis/test/standard/main.go b/v2/internal/staticanalysis/test/standard/main.go
index 93cbc7ea3..3f735d640 100644
--- a/v2/internal/staticanalysis/test/standard/main.go
+++ b/v2/internal/staticanalysis/test/standard/main.go
@@ -5,6 +5,7 @@ import (
"github.com/wailsapp/wails/v2"
"github.com/wailsapp/wails/v2/pkg/options"
+ "github.com/wailsapp/wails/v2/pkg/options/assetserver"
)
//go:embed all:frontend/dist
@@ -16,10 +17,12 @@ func main() {
// Create application with options
err := wails.Run(&options.App{
- Title: "staticanalysis",
- Width: 1024,
- Height: 768,
- Assets: assets,
+ Title: "staticanalysis",
+ Width: 1024,
+ Height: 768,
+ AssetServer: &assetserver.Options{
+ Assets: assets,
+ },
BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1},
OnStartup: app.startup,
Bind: []interface{}{
diff --git a/v2/pkg/options/assetserver/middleware.go b/v2/pkg/options/assetserver/middleware.go
new file mode 100644
index 000000000..b3826ab7d
--- /dev/null
+++ b/v2/pkg/options/assetserver/middleware.go
@@ -0,0 +1,20 @@
+package assetserver
+
+import (
+ "net/http"
+)
+
+// Middleware defines a HTTP middleware that can be applied to the AssetServer.
+// The handler passed as next is the next handler in the chain. One can decide to call the next handler
+// or implement a specialized handling.
+type Middleware func(next http.Handler) http.Handler
+
+// ChainMiddleware allows chaining multiple middlewares to one middleware.
+func ChainMiddleware(middleware ...Middleware) Middleware {
+ return func(h http.Handler) http.Handler {
+ for i := len(middleware) - 1; i >= 0; i-- {
+ h = middleware[i](h)
+ }
+ return h
+ }
+}
diff --git a/v2/pkg/options/assetserver/options.go b/v2/pkg/options/assetserver/options.go
new file mode 100644
index 000000000..0be9a1d3e
--- /dev/null
+++ b/v2/pkg/options/assetserver/options.go
@@ -0,0 +1,35 @@
+package assetserver
+
+import (
+ "io/fs"
+ "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 http.Handler
+
+ // Middleware is a HTTP Middleware which allows to hook into the AssetServer request chain. It allows to skip the default
+ // request handler dynamically, e.g. implement specialized Routing etc.
+ // 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.
+ //
+ // If not defined, the default AssetServer request chain is executed.
+ //
+ // Multiple Middlewares can be chained together with:
+ // ChainMiddleware(middleware ...Middleware) Middleware
+ Middleware Middleware
+}
diff --git a/v2/pkg/options/options.go b/v2/pkg/options/options.go
index 25f619b6b..e6ded464a 100644
--- a/v2/pkg/options/options.go
+++ b/v2/pkg/options/options.go
@@ -8,6 +8,7 @@ import (
"net/http"
"runtime"
+ "github.com/wailsapp/wails/v2/pkg/options/assetserver"
"github.com/wailsapp/wails/v2/pkg/options/linux"
"github.com/wailsapp/wails/v2/pkg/options/mac"
"github.com/wailsapp/wails/v2/pkg/options/windows"
@@ -47,9 +48,13 @@ type App struct {
AlwaysOnTop bool
// BackgroundColour is the background colour of the window
// You can use the options.NewRGB and options.NewRGBA functions to create a new colour
- BackgroundColour *RGBA
- Assets fs.FS
- AssetsHandler http.Handler
+ BackgroundColour *RGBA
+ // Deprecated: Use AssetServer.Assets instead.
+ Assets fs.FS
+ // Deprecated: Use AssetServer.Handler instead.
+ AssetsHandler http.Handler
+ // AssetServer configures the Assets for the application
+ AssetServer *assetserver.Options
Menu *menu.Menu
Logger logger.Logger `json:"-"`
LogLevel logger.LogLevel
diff --git a/v2/pkg/templates/base/main.go.tmpl b/v2/pkg/templates/base/main.go.tmpl
index a8324d1b8..571cf6b10 100644
--- a/v2/pkg/templates/base/main.go.tmpl
+++ b/v2/pkg/templates/base/main.go.tmpl
@@ -5,6 +5,7 @@ import (
"github.com/wailsapp/wails/v2"
"github.com/wailsapp/wails/v2/pkg/options"
+"github.com/wailsapp/wails/v2/pkg/options/assetserver"
)
//go:embed frontend/dist
@@ -16,10 +17,12 @@ app := NewApp()
// Create application with options
err := wails.Run(&options.App{
-Title: "{{.ProjectName}}",
-Width: 1024,
-Height: 768,
-Assets: assets,
+Title: "{{.ProjectName}}",
+Width: 1024,
+Height: 768,
+AssetServer: &assetserver.Options{
+ Assets: assets,
+},
BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1},
OnStartup: app.startup,
Bind: []interface{}{
diff --git a/v2/pkg/templates/generate/plain/main.go.tmpl b/v2/pkg/templates/generate/plain/main.go.tmpl
index d13de5a38..9f3e2fffe 100644
--- a/v2/pkg/templates/generate/plain/main.go.tmpl
+++ b/v2/pkg/templates/generate/plain/main.go.tmpl
@@ -9,6 +9,7 @@ import (
"github.com/wailsapp/wails/v2"
"github.com/wailsapp/wails/v2/pkg/logger"
"github.com/wailsapp/wails/v2/pkg/options"
+"github.com/wailsapp/wails/v2/pkg/options/assetserver"
"github.com/wailsapp/wails/v2/pkg/options/windows"
)
@@ -37,7 +38,9 @@ Frameless: false,
StartHidden: false,
HideWindowOnClose: false,
BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1},
-Assets: assets,
+AssetServer: &assetserver.Options{
+ Assets: assets,
+},
Menu: nil,
Logger: nil,
LogLevel: logger.DEBUG,
diff --git a/v2/pkg/templates/templates/lit-ts/main.go.tmpl b/v2/pkg/templates/templates/lit-ts/main.go.tmpl
index e0f197dee..e24782be3 100644
--- a/v2/pkg/templates/templates/lit-ts/main.go.tmpl
+++ b/v2/pkg/templates/templates/lit-ts/main.go.tmpl
@@ -5,6 +5,7 @@ import (
"github.com/wailsapp/wails/v2"
"github.com/wailsapp/wails/v2/pkg/options"
+ "github.com/wailsapp/wails/v2/pkg/options/assetserver"
)
//go:embed all:frontend/dist
@@ -16,10 +17,12 @@ func main() {
// Create application with options
err := wails.Run(&options.App{
- Title: "{{.ProjectName}}",
- Width: 1024,
- Height: 768,
- Assets: assets,
+ Title: "{{.ProjectName}}",
+ Width: 1024,
+ Height: 768,
+ AssetServer: &assetserver.Options{
+ Assets: assets,
+ },
BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1},
OnStartup: app.startup,
Bind: []interface{}{
diff --git a/v2/pkg/templates/templates/lit/main.go.tmpl b/v2/pkg/templates/templates/lit/main.go.tmpl
index e0f197dee..e24782be3 100644
--- a/v2/pkg/templates/templates/lit/main.go.tmpl
+++ b/v2/pkg/templates/templates/lit/main.go.tmpl
@@ -5,6 +5,7 @@ import (
"github.com/wailsapp/wails/v2"
"github.com/wailsapp/wails/v2/pkg/options"
+ "github.com/wailsapp/wails/v2/pkg/options/assetserver"
)
//go:embed all:frontend/dist
@@ -16,10 +17,12 @@ func main() {
// Create application with options
err := wails.Run(&options.App{
- Title: "{{.ProjectName}}",
- Width: 1024,
- Height: 768,
- Assets: assets,
+ Title: "{{.ProjectName}}",
+ Width: 1024,
+ Height: 768,
+ AssetServer: &assetserver.Options{
+ Assets: assets,
+ },
BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1},
OnStartup: app.startup,
Bind: []interface{}{
diff --git a/v2/pkg/templates/templates/plain/main.go.tmpl b/v2/pkg/templates/templates/plain/main.go.tmpl
index 09d0b8ea3..847803db6 100644
--- a/v2/pkg/templates/templates/plain/main.go.tmpl
+++ b/v2/pkg/templates/templates/plain/main.go.tmpl
@@ -5,6 +5,7 @@ import (
"github.com/wailsapp/wails/v2"
"github.com/wailsapp/wails/v2/pkg/options"
+ "github.com/wailsapp/wails/v2/pkg/options/assetserver"
)
//go:embed all:frontend/src
@@ -16,10 +17,12 @@ func main() {
// Create application with options
err := wails.Run(&options.App{
- Title: "{{.ProjectName}}",
- Width: 1024,
- Height: 768,
- Assets: assets,
+ Title: "{{.ProjectName}}",
+ Width: 1024,
+ Height: 768,
+ AssetServer: &assetserver.Options{
+ Assets: assets,
+ },
BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1},
OnStartup: app.startup,
Bind: []interface{}{
diff --git a/v2/pkg/templates/templates/preact-ts/main.go.tmpl b/v2/pkg/templates/templates/preact-ts/main.go.tmpl
index e0f197dee..e24782be3 100644
--- a/v2/pkg/templates/templates/preact-ts/main.go.tmpl
+++ b/v2/pkg/templates/templates/preact-ts/main.go.tmpl
@@ -5,6 +5,7 @@ import (
"github.com/wailsapp/wails/v2"
"github.com/wailsapp/wails/v2/pkg/options"
+ "github.com/wailsapp/wails/v2/pkg/options/assetserver"
)
//go:embed all:frontend/dist
@@ -16,10 +17,12 @@ func main() {
// Create application with options
err := wails.Run(&options.App{
- Title: "{{.ProjectName}}",
- Width: 1024,
- Height: 768,
- Assets: assets,
+ Title: "{{.ProjectName}}",
+ Width: 1024,
+ Height: 768,
+ AssetServer: &assetserver.Options{
+ Assets: assets,
+ },
BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1},
OnStartup: app.startup,
Bind: []interface{}{
diff --git a/v2/pkg/templates/templates/preact/main.go.tmpl b/v2/pkg/templates/templates/preact/main.go.tmpl
index e0f197dee..e24782be3 100644
--- a/v2/pkg/templates/templates/preact/main.go.tmpl
+++ b/v2/pkg/templates/templates/preact/main.go.tmpl
@@ -5,6 +5,7 @@ import (
"github.com/wailsapp/wails/v2"
"github.com/wailsapp/wails/v2/pkg/options"
+ "github.com/wailsapp/wails/v2/pkg/options/assetserver"
)
//go:embed all:frontend/dist
@@ -16,10 +17,12 @@ func main() {
// Create application with options
err := wails.Run(&options.App{
- Title: "{{.ProjectName}}",
- Width: 1024,
- Height: 768,
- Assets: assets,
+ Title: "{{.ProjectName}}",
+ Width: 1024,
+ Height: 768,
+ AssetServer: &assetserver.Options{
+ Assets: assets,
+ },
BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1},
OnStartup: app.startup,
Bind: []interface{}{
diff --git a/v2/pkg/templates/templates/react-ts/main.go.tmpl b/v2/pkg/templates/templates/react-ts/main.go.tmpl
index e0f197dee..e24782be3 100644
--- a/v2/pkg/templates/templates/react-ts/main.go.tmpl
+++ b/v2/pkg/templates/templates/react-ts/main.go.tmpl
@@ -5,6 +5,7 @@ import (
"github.com/wailsapp/wails/v2"
"github.com/wailsapp/wails/v2/pkg/options"
+ "github.com/wailsapp/wails/v2/pkg/options/assetserver"
)
//go:embed all:frontend/dist
@@ -16,10 +17,12 @@ func main() {
// Create application with options
err := wails.Run(&options.App{
- Title: "{{.ProjectName}}",
- Width: 1024,
- Height: 768,
- Assets: assets,
+ Title: "{{.ProjectName}}",
+ Width: 1024,
+ Height: 768,
+ AssetServer: &assetserver.Options{
+ Assets: assets,
+ },
BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1},
OnStartup: app.startup,
Bind: []interface{}{
diff --git a/v2/pkg/templates/templates/react/main.go.tmpl b/v2/pkg/templates/templates/react/main.go.tmpl
index e0f197dee..e24782be3 100644
--- a/v2/pkg/templates/templates/react/main.go.tmpl
+++ b/v2/pkg/templates/templates/react/main.go.tmpl
@@ -5,6 +5,7 @@ import (
"github.com/wailsapp/wails/v2"
"github.com/wailsapp/wails/v2/pkg/options"
+ "github.com/wailsapp/wails/v2/pkg/options/assetserver"
)
//go:embed all:frontend/dist
@@ -16,10 +17,12 @@ func main() {
// Create application with options
err := wails.Run(&options.App{
- Title: "{{.ProjectName}}",
- Width: 1024,
- Height: 768,
- Assets: assets,
+ Title: "{{.ProjectName}}",
+ Width: 1024,
+ Height: 768,
+ AssetServer: &assetserver.Options{
+ Assets: assets,
+ },
BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1},
OnStartup: app.startup,
Bind: []interface{}{
diff --git a/v2/pkg/templates/templates/svelte-ts/main.go.tmpl b/v2/pkg/templates/templates/svelte-ts/main.go.tmpl
index e0f197dee..e24782be3 100644
--- a/v2/pkg/templates/templates/svelte-ts/main.go.tmpl
+++ b/v2/pkg/templates/templates/svelte-ts/main.go.tmpl
@@ -5,6 +5,7 @@ import (
"github.com/wailsapp/wails/v2"
"github.com/wailsapp/wails/v2/pkg/options"
+ "github.com/wailsapp/wails/v2/pkg/options/assetserver"
)
//go:embed all:frontend/dist
@@ -16,10 +17,12 @@ func main() {
// Create application with options
err := wails.Run(&options.App{
- Title: "{{.ProjectName}}",
- Width: 1024,
- Height: 768,
- Assets: assets,
+ Title: "{{.ProjectName}}",
+ Width: 1024,
+ Height: 768,
+ AssetServer: &assetserver.Options{
+ Assets: assets,
+ },
BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1},
OnStartup: app.startup,
Bind: []interface{}{
diff --git a/v2/pkg/templates/templates/svelte/main.go.tmpl b/v2/pkg/templates/templates/svelte/main.go.tmpl
index e0f197dee..e24782be3 100644
--- a/v2/pkg/templates/templates/svelte/main.go.tmpl
+++ b/v2/pkg/templates/templates/svelte/main.go.tmpl
@@ -5,6 +5,7 @@ import (
"github.com/wailsapp/wails/v2"
"github.com/wailsapp/wails/v2/pkg/options"
+ "github.com/wailsapp/wails/v2/pkg/options/assetserver"
)
//go:embed all:frontend/dist
@@ -16,10 +17,12 @@ func main() {
// Create application with options
err := wails.Run(&options.App{
- Title: "{{.ProjectName}}",
- Width: 1024,
- Height: 768,
- Assets: assets,
+ Title: "{{.ProjectName}}",
+ Width: 1024,
+ Height: 768,
+ AssetServer: &assetserver.Options{
+ Assets: assets,
+ },
BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1},
OnStartup: app.startup,
Bind: []interface{}{
diff --git a/v2/pkg/templates/templates/vanilla-ts/main.go.tmpl b/v2/pkg/templates/templates/vanilla-ts/main.go.tmpl
index e0f197dee..e24782be3 100644
--- a/v2/pkg/templates/templates/vanilla-ts/main.go.tmpl
+++ b/v2/pkg/templates/templates/vanilla-ts/main.go.tmpl
@@ -5,6 +5,7 @@ import (
"github.com/wailsapp/wails/v2"
"github.com/wailsapp/wails/v2/pkg/options"
+ "github.com/wailsapp/wails/v2/pkg/options/assetserver"
)
//go:embed all:frontend/dist
@@ -16,10 +17,12 @@ func main() {
// Create application with options
err := wails.Run(&options.App{
- Title: "{{.ProjectName}}",
- Width: 1024,
- Height: 768,
- Assets: assets,
+ Title: "{{.ProjectName}}",
+ Width: 1024,
+ Height: 768,
+ AssetServer: &assetserver.Options{
+ Assets: assets,
+ },
BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1},
OnStartup: app.startup,
Bind: []interface{}{
diff --git a/v2/pkg/templates/templates/vanilla/main.go.tmpl b/v2/pkg/templates/templates/vanilla/main.go.tmpl
index e0f197dee..e24782be3 100644
--- a/v2/pkg/templates/templates/vanilla/main.go.tmpl
+++ b/v2/pkg/templates/templates/vanilla/main.go.tmpl
@@ -5,6 +5,7 @@ import (
"github.com/wailsapp/wails/v2"
"github.com/wailsapp/wails/v2/pkg/options"
+ "github.com/wailsapp/wails/v2/pkg/options/assetserver"
)
//go:embed all:frontend/dist
@@ -16,10 +17,12 @@ func main() {
// Create application with options
err := wails.Run(&options.App{
- Title: "{{.ProjectName}}",
- Width: 1024,
- Height: 768,
- Assets: assets,
+ Title: "{{.ProjectName}}",
+ Width: 1024,
+ Height: 768,
+ AssetServer: &assetserver.Options{
+ Assets: assets,
+ },
BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1},
OnStartup: app.startup,
Bind: []interface{}{
diff --git a/v2/pkg/templates/templates/vue-ts/main.go.tmpl b/v2/pkg/templates/templates/vue-ts/main.go.tmpl
index e0f197dee..e24782be3 100644
--- a/v2/pkg/templates/templates/vue-ts/main.go.tmpl
+++ b/v2/pkg/templates/templates/vue-ts/main.go.tmpl
@@ -5,6 +5,7 @@ import (
"github.com/wailsapp/wails/v2"
"github.com/wailsapp/wails/v2/pkg/options"
+ "github.com/wailsapp/wails/v2/pkg/options/assetserver"
)
//go:embed all:frontend/dist
@@ -16,10 +17,12 @@ func main() {
// Create application with options
err := wails.Run(&options.App{
- Title: "{{.ProjectName}}",
- Width: 1024,
- Height: 768,
- Assets: assets,
+ Title: "{{.ProjectName}}",
+ Width: 1024,
+ Height: 768,
+ AssetServer: &assetserver.Options{
+ Assets: assets,
+ },
BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1},
OnStartup: app.startup,
Bind: []interface{}{
diff --git a/v2/pkg/templates/templates/vue/main.go.tmpl b/v2/pkg/templates/templates/vue/main.go.tmpl
index e0f197dee..e24782be3 100644
--- a/v2/pkg/templates/templates/vue/main.go.tmpl
+++ b/v2/pkg/templates/templates/vue/main.go.tmpl
@@ -5,6 +5,7 @@ import (
"github.com/wailsapp/wails/v2"
"github.com/wailsapp/wails/v2/pkg/options"
+ "github.com/wailsapp/wails/v2/pkg/options/assetserver"
)
//go:embed all:frontend/dist
@@ -16,10 +17,12 @@ func main() {
// Create application with options
err := wails.Run(&options.App{
- Title: "{{.ProjectName}}",
- Width: 1024,
- Height: 768,
- Assets: assets,
+ Title: "{{.ProjectName}}",
+ Width: 1024,
+ Height: 768,
+ AssetServer: &assetserver.Options{
+ Assets: assets,
+ },
BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1},
OnStartup: app.startup,
Bind: []interface{}{
diff --git a/website/docs/guides/dynamic-assets.mdx b/website/docs/guides/dynamic-assets.mdx
index 07202e0a4..806accf18 100644
--- a/website/docs/guides/dynamic-assets.mdx
+++ b/website/docs/guides/dynamic-assets.mdx
@@ -19,6 +19,7 @@ import (
"fmt"
"github.com/wailsapp/wails/v2"
"github.com/wailsapp/wails/v2/pkg/options"
+ "github.com/wailsapp/wails/v2/pkg/options/assetserver"
"net/http"
"os"
"strings"
@@ -54,13 +55,15 @@ func main() {
// Create application with options
err := wails.Run(&options.App{
- Title: "helloworld",
- Width: 1024,
- Height: 768,
- Assets: assets,
+ Title: "helloworld",
+ Width: 1024,
+ Height: 768,
+ AssetServer: &assetserver.Options{
+ Assets: assets,
+ Handler: NewFileLoader(),
+ },
BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 255},
OnStartup: app.startup,
- AssetsHandler: NewFileLoader(),
Bind: []interface{}{
app,
},
diff --git a/website/docs/guides/frameless.mdx b/website/docs/guides/frameless.mdx
index 4d5798474..07d8d2d25 100644
--- a/website/docs/guides/frameless.mdx
+++ b/website/docs/guides/frameless.mdx
@@ -38,6 +38,7 @@ import (
"github.com/wailsapp/wails/v2"
"github.com/wailsapp/wails/v2/pkg/options"
+ "github.com/wailsapp/wails/v2/pkg/options/assetserver"
)
//go:embed all:frontend/dist
@@ -49,15 +50,17 @@ func main() {
// Create application with options
err := wails.Run(&options.App{
- Title: "alwaysontop",
- Width: 1024,
- Height: 768,
- Assets: assets,
+ Title: "alwaysontop",
+ Width: 1024,
+ Height: 768,
+ AssetServer: &assetserver.Options{
+ Assets: assets,
+ },
Frameless: true,
CSSDragProperty: "widows",
CSSDragValue: "1",
Bind: []interface{}{
- app,
+ app,
},
})
diff --git a/website/docs/guides/migrating.mdx b/website/docs/guides/migrating.mdx
index 1fcdcc958..86549707d 100644
--- a/website/docs/guides/migrating.mdx
+++ b/website/docs/guides/migrating.mdx
@@ -31,7 +31,9 @@ In v2, there is just a single method, `wails.Run()`, that accepts [application o
Title: "MyApp",
Width: 800,
Height: 600,
- Assets: assets,
+ AssetServer: &assetserver.Options{
+ Assets: assets,
+ },
Bind: []interface{}{
basic,
},
@@ -165,7 +167,9 @@ var assets embed.FS
func main() {
err := wails.Run(&options.App{
/* Other Options */
- Assets: assets,
+ AssetServer: &assetserver.Options{
+ Assets: assets,
+ },
})
}
```
diff --git a/website/docs/howdoesitwork.mdx b/website/docs/howdoesitwork.mdx
index 872e847f3..fb23b3dfc 100644
--- a/website/docs/howdoesitwork.mdx
+++ b/website/docs/howdoesitwork.mdx
@@ -33,6 +33,7 @@ import (
"github.com/wailsapp/wails/v2"
"github.com/wailsapp/wails/v2/pkg/options"
+ "github.com/wailsapp/wails/v2/pkg/options/assetserver"
)
//go:embed all:frontend/dist
@@ -43,12 +44,14 @@ func main() {
app := &App{}
err := wails.Run(&options.App{
- Title: "Basic Demo",
- Width: 1024,
- Height: 768,
- Assets: &assets,
- OnStartup: app.startup,
- OnShutdown: app.shutdown,
+ Title: "Basic Demo",
+ Width: 1024,
+ Height: 768,
+ AssetServer: &assetserver.Options{
+ Assets: assets,
+ },
+ OnStartup: app.startup,
+ OnShutdown: app.shutdown,
Bind: []interface{}{
app,
},
@@ -147,6 +150,7 @@ import (
"github.com/wailsapp/wails/v2"
"github.com/wailsapp/wails/v2/pkg/options"
+ "github.com/wailsapp/wails/v2/pkg/options/assetserver"
)
//go:embed all:frontend/dist
@@ -157,10 +161,12 @@ func main() {
app := &App{}
err := wails.Run(&options.App{
- Title: "Basic Demo",
- Width: 1024,
- Height: 768,
- Assets: &assets,
+ Title: "Basic Demo",
+ Width: 1024,
+ Height: 768,
+ AssetServer: &assetserver.Options{
+ Assets: assets,
+ },
Bind: []interface{}{
app,
},
@@ -185,10 +191,12 @@ You may bind as many structs as you like. Just make sure you create an instance
```go {8-10}
//...
err := wails.Run(&options.App{
- Title: "Basic Demo",
- Width: 1024,
- Height: 768,
- Assets: &assets,
+ Title: "Basic Demo",
+ Width: 1024,
+ Height: 768,
+ AssetServer: &assetserver.Options{
+ Assets: assets,
+ },
Bind: []interface{}{
app,
&mystruct1{},
diff --git a/website/docs/reference/options.mdx b/website/docs/reference/options.mdx
index 4f2b1227a..baeb92876 100644
--- a/website/docs/reference/options.mdx
+++ b/website/docs/reference/options.mdx
@@ -10,7 +10,13 @@ The `Options.App` struct contains the application configuration.
It is passed to the `wails.Run()` method:
```go title="Example"
-import "github.com/wailsapp/wails/v2/pkg/options"
+import (
+ "github.com/wailsapp/wails/v2/pkg/options"
+ "github.com/wailsapp/wails/v2/pkg/options/assetserver"
+ "github.com/wailsapp/wails/v2/pkg/options/linux"
+ "github.com/wailsapp/wails/v2/pkg/options/mac"
+ "github.com/wailsapp/wails/v2/pkg/options/windows"
+)
func main() {
@@ -29,8 +35,11 @@ func main() {
HideWindowOnClose: false,
BackgroundColour: &options.RGBA{R: 0, G: 0, B: 0, A: 255},
AlwaysOnTop: false,
- Assets: assets,
- AssetsHandler: assetsHandler,
+ AssetServer: &assetserver.Options{
+ Assets: assets,
+ Handler: assetsHandler,
+ Middleware: assetsMidldeware,
+ },
Menu: app.applicationMenu(),
Logger: nil,
LogLevel: logger.DEBUG,
@@ -213,19 +222,20 @@ Type: `bool`
### Assets
-The frontend assets to be used by the application. Requires an `index.html` file.
-
-Name: Assets
-Type: `embed.FS`
+Deprecated: Please use Assets on [AssetServer specific options](#assetserver).
### AssetsHandler
-
+Deprecated: Please use AssetsHandler on [AssetServer specific options](#assetserver).
-The assets handler is a generic `http.Handler` which will be called for any non GET request on the assets server
-and for GET requests which can not be served from the `assets` because the file is not found.
+### AssetServer
-| Value | Win | Mac | Lin |
+This defines AssetServer specific options. It allows to customize the AssetServer with static assets, serving assets
+dynamically with an `http.Handler` or hook into the request chain with an `assetserver.Middleware`.
+
+Not all features of an `http.Request` are currently supported, please see the following feature matrix:
+
+| Feature | Win | Mac | Lin |
| ----------------------- | --- | --- | --- |
| GET | ✅ | ✅ | ✅ |
| POST | ✅ | ✅ | ❌ |
@@ -239,16 +249,55 @@ and for GET requests which can not be served from the `assets` because the file
| Response Headers | ✅ | ✅ | ❌ |
| Response Body | ✅ | ✅ | ✅ |
| Response Body Streaming | ❌ | ❌ | ✅ |
+| WebSockets | ❌ | ❌ | ❌ |
NOTE: Linux is currently very limited due to targeting a WebKit2GTK Version < 2.36.0. In the future some features will be
supported by the introduction of WebKit2GTK 2.36.0+ support.
+Name: AssetServer
+Type: `*assetserver.Options`
+
+#### Assets
+
+The static frontend assets to be used by the application.
+
+A GET request is first tried to be served from this `fs.FS`. If the `fs.FS` returns `os.ErrNotExist` for that file,
+the request handling will fallback to the [Handler](#handler) and tries to serve the GET request from it.
+
+If set to nil, all GET requests will be forwarded to [Handler](#handler).
+
+Name: Assets
+Type: `fs.FS`
+
+#### Handler
+
+The assets handler is a generic `http.Handler` for fallback handling of assets that can't be found.
+
+The handler will be called for every GET request that can't be served from [Assets](#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`
+
NOTE: When used in combination with a Frontend DevServer there might be limitations, eg. Vite serves the index.html
on every path, that does not contain a file extension.
Name: AssetsHandler
Type: `http.Handler`
+#### Middleware
+
+Middleware is a HTTP Middleware which allows to hook into the AssetServer request chain. It allows to skip the default
+request handler dynamically, e.g. implement specialized Routing etc.
+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.
+
+If not defined, the default AssetServer request chain is executed.
+
+Name: Middleware
+Type: `assetserver.Middleware`
+
### Menu
The menu to be used by the application. More details about Menus in the [Menu Reference](../reference/runtime/menu.mdx).