diff --git a/v2/cmd/wails/internal/dev/dev.go b/v2/cmd/wails/internal/dev/dev.go index b7fc4d10d..8d11edbf7 100644 --- a/v2/cmd/wails/internal/dev/dev.go +++ b/v2/cmd/wails/internal/dev/dev.go @@ -318,9 +318,6 @@ func restartApp(buildOptions *build.Options, debugBinaryProcess *process.Process os.Setenv("assetdir", f.AssetDir) os.Setenv("devserver", f.DevServer) os.Setenv("frontenddevserverurl", f.FrontendDevServerURL) - if legacyUseDevServerInsteadofCustomScheme { - os.Setenv("legacyusedevsererinsteadofcustomscheme", "true") - } // Start up new binary with correct args newProcess := process.NewProcess(appBinary, args...) diff --git a/v2/internal/app/app_dev.go b/v2/internal/app/app_dev.go index 8373d399f..38aada698 100644 --- a/v2/internal/app/app_dev.go +++ b/v2/internal/app/app_dev.go @@ -106,15 +106,13 @@ func CreateApp(appoptions *options.App) (*App, error) { } if frontendDevServerURL != "" { - if os.Getenv("legacyusedevsererinsteadofcustomscheme") != "" { - startURL, err := url.Parse("http://" + devServer) - if err != nil { - return nil, err - } - - ctx = context.WithValue(ctx, "starturl", startURL) + _, port, err := net.SplitHostPort(devServer) + if err != nil { + return nil, fmt.Errorf("unable to determine port of DevServer: %s", err) } + ctx = context.WithValue(ctx, "assetserverport", port) + ctx = context.WithValue(ctx, "frontenddevserverurl", frontendDevServerURL) externalURL, err := url.Parse(frontendDevServerURL) diff --git a/v2/internal/frontend/desktop/darwin/frontend.go b/v2/internal/frontend/desktop/darwin/frontend.go index 5187be2c0..b714a2c3b 100644 --- a/v2/internal/frontend/desktop/darwin/frontend.go +++ b/v2/internal/frontend/desktop/darwin/frontend.go @@ -19,6 +19,7 @@ import ( "fmt" "html/template" "log" + "net" "net/url" "unsafe" @@ -78,6 +79,10 @@ func NewFrontend(ctx context.Context, appoptions *options.App, myLogger *logger. if _starturl, _ := ctx.Value("starturl").(*url.URL); _starturl != nil { result.startURL = _starturl } else { + if port, _ := ctx.Value("assetserverport").(string); port != "" { + result.startURL.Host = net.JoinHostPort(result.startURL.Host+".localhost", port) + } + var bindings string var err error if _obfuscated, _ := ctx.Value("obfuscated").(bool); !_obfuscated { diff --git a/v2/internal/frontend/desktop/linux/frontend.go b/v2/internal/frontend/desktop/linux/frontend.go index e02c6a928..58b8d746b 100644 --- a/v2/internal/frontend/desktop/linux/frontend.go +++ b/v2/internal/frontend/desktop/linux/frontend.go @@ -78,6 +78,7 @@ import ( "encoding/json" "fmt" "log" + "net" "net/url" "os" "runtime" @@ -149,6 +150,10 @@ func NewFrontend(ctx context.Context, appoptions *options.App, myLogger *logger. if _starturl, _ := ctx.Value("starturl").(*url.URL); _starturl != nil { result.startURL = _starturl } else { + if port, _ := ctx.Value("assetserverport").(string); port != "" { + result.startURL.Host = net.JoinHostPort(result.startURL.Host+".localhost", port) + } + var bindings string var err error if _obfuscated, _ := ctx.Value("obfuscated").(bool); !_obfuscated { diff --git a/v2/internal/frontend/desktop/windows/frontend.go b/v2/internal/frontend/desktop/windows/frontend.go index cf6da9760..82289e054 100644 --- a/v2/internal/frontend/desktop/windows/frontend.go +++ b/v2/internal/frontend/desktop/windows/frontend.go @@ -9,6 +9,7 @@ import ( "fmt" "io" "log" + "net" "net/http" "net/http/httptest" "net/url" @@ -92,6 +93,10 @@ func NewFrontend(ctx context.Context, appoptions *options.App, myLogger *logger. return result } + if port, _ := ctx.Value("assetserverport").(string); port != "" { + result.startURL.Host = net.JoinHostPort(result.startURL.Host, port) + } + var bindings string var err error if _obfuscated, _ := ctx.Value("obfuscated").(bool); !_obfuscated { @@ -589,8 +594,16 @@ func (f *Frontend) processRequest(req *edge.ICoreWebView2WebResourceRequest, arg headers = append(headers, fmt.Sprintf("%s: %s", k, strings.Join(v, ","))) } + code := rw.Code + if code == http.StatusNotModified { + // WebView2 has problems when a request returns a 304 status code and the WebView2 is going to hang for other + // requests including IPC calls. + f.logger.Error("%s: AssetServer returned 304 - StatusNotModified which are going to hang WebView2, changed code to 505 - StatusInternalServerError", uri) + code = http.StatusInternalServerError + } + env := f.chromium.Environment() - response, err := env.CreateWebResourceResponse(rw.Body.Bytes(), rw.Code, http.StatusText(rw.Code), strings.Join(headers, "\n")) + response, err := env.CreateWebResourceResponse(rw.Body.Bytes(), code, http.StatusText(code), strings.Join(headers, "\n")) if err != nil { f.logger.Error("CreateWebResourceResponse Error: %s", err) return @@ -829,6 +842,12 @@ func coreWebview2RequestToHttpRequest(coreReq *edge.ICoreWebView2WebResourceRequ } } + // WebView2 has problems when a request returns a 304 status code and the WebView2 is going to hang for other + // requests including IPC calls. + // So prevent 304 status codes by removing the headers that are used in combinationwith caching. + header.Del("If-Modified-Since") + header.Del("If-None-Match") + method, err := coreReq.GetMethod() if err != nil { return nil, fmt.Errorf("GetMethod Error: %s", err) diff --git a/v2/internal/frontend/devserver/devserver.go b/v2/internal/frontend/devserver/devserver.go index 35b67e86a..3d623ed6d 100644 --- a/v2/internal/frontend/devserver/devserver.go +++ b/v2/internal/frontend/devserver/devserver.go @@ -97,13 +97,17 @@ func (d *DevWebServer) Run(ctx context.Context) error { log.Fatal(err) } - assetServer, err := assetserver.NewDevAssetServer(assetHandler, wsHandler, bindingsJSON, ctx.Value("assetdir") != nil, myLogger, runtime.RuntimeAssetsBundle) + assetServer, err := assetserver.NewDevAssetServer(assetHandler, bindingsJSON, ctx.Value("assetdir") != nil, myLogger, runtime.RuntimeAssetsBundle) if err != nil { log.Fatal(err) } d.server.Any("/*", func(c echo.Context) error { - assetServer.ServeHTTP(c.Response(), c.Request()) + if c.IsWebSocket() { + wsHandler.ServeHTTP(c.Response(), c.Request()) + } else { + assetServer.ServeHTTP(c.Response(), c.Request()) + } return nil }) diff --git a/v2/pkg/assetserver/assetserver.go b/v2/pkg/assetserver/assetserver.go index 78647b0c9..625c3f245 100644 --- a/v2/pkg/assetserver/assetserver.go +++ b/v2/pkg/assetserver/assetserver.go @@ -32,7 +32,6 @@ type RuntimeHandler interface { type AssetServer struct { handler http.Handler - wsHandler http.Handler runtimeJS []byte ipcJS func(*http.Request) []byte @@ -107,12 +106,8 @@ func (d *AssetServer) AddPluginScript(pluginName string, script string) { 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) - } + // WebSockets are not supported by the AssetServer + rw.WriteHeader(http.StatusNotImplemented) return } diff --git a/v2/pkg/assetserver/assetserver_dev.go b/v2/pkg/assetserver/assetserver_dev.go index fb13b3a23..f6a2a0d2f 100644 --- a/v2/pkg/assetserver/assetserver_dev.go +++ b/v2/pkg/assetserver/assetserver_dev.go @@ -13,13 +13,12 @@ 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(handler http.Handler, wsHandler http.Handler, bindingsJSON string, servingFromDisk bool, logger Logger, runtime RuntimeAssets) (*AssetServer, error) { +func NewDevAssetServer(handler 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 } - result.wsHandler = wsHandler result.appendSpinnerToBody = true result.ipcJS = func(req *http.Request) []byte { if strings.Contains(req.UserAgent(), WailsUserAgentValue) { diff --git a/v2/pkg/assetserver/webview/request_darwin.go b/v2/pkg/assetserver/webview/request_darwin.go index 653c19506..f0e85780b 100644 --- a/v2/pkg/assetserver/webview/request_darwin.go +++ b/v2/pkg/assetserver/webview/request_darwin.go @@ -8,6 +8,7 @@ package webview #import #import +#include static void URLSchemeTaskRetain(void *wkUrlSchemeTask) { id urlSchemeTask = (id) wkUrlSchemeTask; @@ -44,9 +45,7 @@ static const char * URLSchemeTaskRequestHeadersJSON(void *wkUrlSchemeTask) { NSString* headerString = [[[NSString alloc] initWithData:headerData encoding:NSUTF8StringEncoding] autorelease]; const char * headerJSON = [headerString UTF8String]; - char * headersOut = malloc(strlen(headerJSON)); - strcpy(headersOut, headerJSON); - return headersOut; + return strdup(headerJSON); } } diff --git a/v2/pkg/assetserver/webview/webkit2_legacy.go b/v2/pkg/assetserver/webview/webkit2_legacy.go index 65454abfc..1a87fe96a 100644 --- a/v2/pkg/assetserver/webview/webkit2_legacy.go +++ b/v2/pkg/assetserver/webview/webkit2_legacy.go @@ -24,7 +24,12 @@ func webkit_uri_scheme_request_get_http_method(_ *C.WebKitURISchemeRequest) stri } func webkit_uri_scheme_request_get_http_headers(_ *C.WebKitURISchemeRequest) http.Header { - return http.Header{} + // Fake some basic default headers that are needed if e.g. request are being proxied to the an external sever, like + // we do in the devserver. + h := http.Header{} + h.Add("Accept", "*/*") + h.Add("User-Agent", "wails.io/605.1.15") + return h } func webkit_uri_scheme_request_get_http_body(_ *C.WebKitURISchemeRequest) io.ReadCloser { diff --git a/website/src/pages/changelog.mdx b/website/src/pages/changelog.mdx index 5933b4556..c762fb418 100644 --- a/website/src/pages/changelog.mdx +++ b/website/src/pages/changelog.mdx @@ -17,6 +17,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Breaking Changes - The Go WebView2Loader allowed env variable and registry overrides to change the behaviour of WebView2. This is not possible when using the native WebView2Loader with Wails and should not be possible according to [PR](https://github.com/wailsapp/wails/pull/1771). Changed by @stffabi in [PR](https://github.com/wailsapp/wails/pull/2668) +- `wails dev` now uses the custom schemes `wails://` on macOS and Linux for all Vite versions. This also fixes missing reloads after multiple fast savings on Linux and Windows. Changed by @stffabi in [PR](https://github.com/wailsapp/wails/pull/2664) + +### Fixed + +- Fixed segfaults during fast reloads of requests on macOS. Fixed by @stffabi in [PR](https://github.com/wailsapp/wails/pull/2664) +- Fixed devserver on Linux for older WebKit2GTK versions < 2.36. Fixed by @stffabi in [PR](https://github.com/wailsapp/wails/pull/2664) +- Fixed devserver on Windows that might have triggered the WebView2 into a hang. Fixed by @stffabi in [PR](https://github.com/wailsapp/wails/pull/2664) ## v2.5.0 - 2023-05-13