5
0
mirror of https://github.com/wailsapp/wails.git synced 2025-05-03 06:01:52 +08:00
wails/v2/internal/frontend/devserver/external.go
stffabi 6d09a45a30
[v2] Add support for AssetsHandler (#1325)
* [website] Fix devserver default value doc

* [v2] Add support for AssetsHandler

AssetsHandler is a http.Handler delegate, which gets called
as a fallback for all Non-GET requests and for GET requests
for which the Assets didn’t find the file.

Known Limitations on Linux:
- All requests are GET requests
- No request headers
- No request body
- No response status code, only StatusOK will be returned
- No response headers

Known Limitations on Windows:
-  Request body is leaking memory. Seems to be a bug in
    WebView2, investigation angoing.

Most of these limitations on Linux will be fixed in the future with
adding support for Webkit2Gtk 2.36.0+.

* [v2, linux] Add response streaming support

The complete response won’t be held anymore in memory and will
be streamed to WebKit2.

Co-authored-by: Lea Anthony <lea.anthony@gmail.com>
2022-04-12 20:18:27 +10:00

79 lines
1.7 KiB
Go

//go:build dev
// +build dev
package devserver
import (
"errors"
"fmt"
"net/http"
"net/http/httputil"
"net/url"
"github.com/labstack/echo/v4"
"github.com/wailsapp/wails/v2/internal/logger"
)
func newExternalDevServerAssetHandler(logger *logger.Logger, url *url.URL, handler http.Handler) http.Handler {
errSkipProxy := fmt.Errorf("skip proxying")
proxy := httputil.NewSingleHostReverseProxy(url)
baseDirector := proxy.Director
proxy.Director = func(r *http.Request) {
baseDirector(r)
if logger != nil {
logger.Debug("[ExternalAssetHandler] Loading '%s'", r.URL)
}
}
proxy.ModifyResponse = func(res *http.Response) error {
if handler == 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 handler != nil && errors.Is(err, errSkipProxy) {
if logger != nil {
logger.Debug("[ExternalAssetHandler] Loading '%s' failed, using AssetHandler", r.URL)
}
handler.ServeHTTP(rw, r)
} else {
if logger != nil {
logger.Error("[ExternalAssetHandler] Proxy error: %v", err)
}
rw.WriteHeader(http.StatusBadGateway)
}
}
e := echo.New()
e.Any("/*",
func(c echo.Context) error {
req := c.Request()
rw := c.Response()
if c.IsWebSocket() || req.Method == http.MethodGet {
proxy.ServeHTTP(rw, req)
return nil
}
if handler != nil {
handler.ServeHTTP(rw, req)
return nil
}
return c.NoContent(http.StatusMethodNotAllowed)
})
return e
}