[assetserver] Introduce middleware and extract options (#2016)

* [assetserver] Add support for HTTP Middlewares

* [dev] Disable frontend DevServer if no Assets has been defined and inform user

* [dev] Consistent WebSocket behaviour in dev and prod mode for assets handler and middleware

In prod mode we can't support WebSockets so make sure the
assets handler and middleware never see WebSockets in dev mode.

* [templates] Migrate to new AssetServer option

* [docs] Add assetserver.Options to the reference
This commit is contained in:
stffabi
2022-10-29 23:15:15 +02:00
committed by GitHub
parent 4cd89e1507
commit 638caf72f0
37 changed files with 397 additions and 150 deletions
+11 -3
View File
@@ -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)
}
+18 -13
View File
@@ -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
}