5
0
mirror of https://github.com/wailsapp/wails.git synced 2025-05-21 11:29:29 +08:00

[windows] Serve assets async

This commit is contained in:
Lea Anthony 2023-10-05 19:18:32 +11:00
parent 9b88c8afda
commit 5958d9c646
No known key found for this signature in database
GPG Key ID: 33DAF7BB90A58405
10 changed files with 387 additions and 144 deletions

View File

@ -24,13 +24,14 @@ require (
github.com/matryer/is v1.4.0
github.com/mattn/go-colorable v0.1.13
github.com/mattn/go-isatty v0.0.19
github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8
github.com/pkg/errors v0.9.1
github.com/pterm/pterm v0.12.51
github.com/samber/lo v1.38.1
github.com/tc-hib/winres v0.1.6
github.com/wailsapp/go-webview2 v1.0.6-0.20230901120557-e959fdf1ccc3
github.com/wailsapp/go-webview2 v1.0.7
github.com/wailsapp/mimetype v1.4.1
github.com/wailsapp/wails/v2 v2.6.0
golang.org/x/net v0.10.0
golang.org/x/sys v0.11.0
modernc.org/sqlite v1.21.0
@ -74,10 +75,10 @@ require (
github.com/sergi/go-diff v1.2.0 // indirect
github.com/xanzy/ssh-agent v0.3.0 // indirect
github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 // indirect
golang.org/x/crypto v0.1.0 // indirect
golang.org/x/crypto v0.9.0 // indirect
golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df // indirect
golang.org/x/image v0.5.0 // indirect
golang.org/x/mod v0.11.0 // indirect
golang.org/x/mod v0.12.0 // indirect
golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43 // indirect
golang.org/x/sync v0.3.0 // indirect
golang.org/x/term v0.11.0 // indirect

View File

@ -278,8 +278,8 @@ github.com/mrjones/oauth v0.0.0-20180629183705-f4e24b6d100c/go.mod h1:skjdDftzkF
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2 h1:acNfDZXmm28D2Yg/c3ALnZStzNaZMSagpbr96vY6Zjc=
github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI=
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU=
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@ -338,8 +338,12 @@ github.com/tmclane/purego v0.0.0-20230818202843-0b72c8c9140f h1:/HXk9aFXP97CJRzO
github.com/tmclane/purego v0.0.0-20230818202843-0b72c8c9140f/go.mod h1:ah1In8AOtksoNK6yk5z1HTJeUkC1Ez4Wk2idgGslMwQ=
github.com/wailsapp/go-webview2 v1.0.6-0.20230901120557-e959fdf1ccc3 h1:lN7ATT1NZrwKjn2F/VSRJxJeWQZvuypzRHeLwr2No4Q=
github.com/wailsapp/go-webview2 v1.0.6-0.20230901120557-e959fdf1ccc3/go.mod h1:Uk2BePfCRzttBBjFrBmqKGJd41P6QIHeV9kTgIeOZNo=
github.com/wailsapp/go-webview2 v1.0.7 h1:s95+7irJsAsTy1RsjJ6N0cYX7tZ4gP7Uzawds0L2urs=
github.com/wailsapp/go-webview2 v1.0.7/go.mod h1:Uk2BePfCRzttBBjFrBmqKGJd41P6QIHeV9kTgIeOZNo=
github.com/wailsapp/mimetype v1.4.1 h1:pQN9ycO7uo4vsUUuPeHEYoUkLVkaRntMnHJxVwYhwHs=
github.com/wailsapp/mimetype v1.4.1/go.mod h1:9aV5k31bBOv5z6u+QP8TltzvNGJPmNJD4XlAL3U+j3o=
github.com/wailsapp/wails/v2 v2.6.0 h1:EyH0zR/EO6dDiqNy8qU5spaXDfkluiq77xrkabPYD4c=
github.com/wailsapp/wails/v2 v2.6.0/go.mod h1:WBG9KKWuw0FKfoepBrr/vRlyTmHaMibWesK3yz6nNiM=
github.com/xanzy/ssh-agent v0.3.0 h1:wUMzuKtKilRgBAD1sUb8gOwwRr2FGoBVumcjoOACClI=
github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0=
github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 h1:QldyIu/L63oPpyvQmHgvgickp1Yw510KJOqX7H24mg8=
@ -364,8 +368,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU=
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g=
golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@ -403,8 +407,8 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.11.0 h1:bUO06HqtnRcc/7l71XBe4WcqTZ+3AH1J59zWDDwLKgU=
golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc=
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=

View File

@ -1,84 +0,0 @@
package assetserver
import (
"io"
"net/http"
"net/http/httptest"
"github.com/wailsapp/wails/v3/internal/assetserver/webview"
)
// ProcessHTTPRequest processes the HTTP Request by faking a golang HTTP Server.
// The request will be finished with a StatusNotImplemented code if no handler has written to the response.
func (d *AssetServer) ProcessHTTPRequestLegacy(rw http.ResponseWriter, reqGetter func() (*http.Request, error)) {
d.processWebViewRequest(&legacyRequest{reqGetter: reqGetter, rw: rw})
}
type legacyRequest struct {
req *http.Request
rw http.ResponseWriter
reqGetter func() (*http.Request, error)
}
func (r *legacyRequest) URL() (string, error) {
req, err := r.request()
if err != nil {
return "", err
}
return req.URL.String(), nil
}
func (r *legacyRequest) Method() (string, error) {
req, err := r.request()
if err != nil {
return "", err
}
return req.Method, nil
}
func (r *legacyRequest) Header() (http.Header, error) {
req, err := r.request()
if err != nil {
return nil, err
}
return req.Header, nil
}
func (r *legacyRequest) Body() (io.ReadCloser, error) {
req, err := r.request()
if err != nil {
return nil, err
}
return req.Body, nil
}
func (r legacyRequest) Response() webview.ResponseWriter {
return &legacyRequestNoOpCloserResponseWriter{ResponseWriter: r.rw}
}
func (r legacyRequest) Close() error { return nil }
func (r *legacyRequest) request() (*http.Request, error) {
if r.req != nil {
return r.req, nil
}
req, err := r.reqGetter()
if err != nil {
return nil, err
}
r.req = req
return req, nil
}
type legacyRequestNoOpCloserResponseWriter struct {
http.ResponseWriter
code int
}
func (*legacyRequestNoOpCloserResponseWriter) Finish() {}
func (r *legacyRequestNoOpCloserResponseWriter) Code() int {
return r.ResponseWriter.(*httptest.ResponseRecorder).Code
}

View File

@ -26,19 +26,15 @@ type assetServerWebView struct {
func (d *AssetServer) ServeWebViewRequest(req webview.Request) {
d.dispatchInit.Do(func() {
workers := d.dispatchWorkers
if workers == 0 {
workers = 10
if workers <= 0 {
return
}
workerC := make(chan webview.Request, workers*2)
for i := 0; i < workers; i++ {
go func() {
for req := range workerC {
uri, _ := req.URL()
d.processWebViewRequest(req)
if err := req.Close(); err != nil {
d.logError("Unable to call close for request for uri '%s'", uri)
}
}
}()
}
@ -49,21 +45,40 @@ func (d *AssetServer) ServeWebViewRequest(req webview.Request) {
d.dispatchReqC = dispatchC
})
d.dispatchReqC <- req
if d.dispatchReqC == nil {
go d.processWebViewRequest(req)
} else {
d.dispatchReqC <- req
}
}
func (d *AssetServer) processWebViewRequest(r webview.Request) {
uri, _ := r.URL()
d.processWebViewRequestInternal(r)
if err := r.Close(); err != nil {
d.logError("Unable to call close for request for uri '%s'", uri)
}
}
// processHTTPRequest processes the HTTP Request by faking a golang HTTP Server.
// The request will be finished with a StatusNotImplemented code if no handler has written to the response.
func (d *AssetServer) processWebViewRequest(r webview.Request) {
func (d *AssetServer) processWebViewRequestInternal(r webview.Request) {
uri := "unknown"
var err error
wrw := r.Response()
defer wrw.Finish()
defer func() {
if err := wrw.Finish(); err != nil {
d.logError("Error finishing request '%s': %s", uri, err)
}
}()
var rw http.ResponseWriter = &contentTypeSniffer{rw: wrw} // Make sure we have a Content-Type sniffer
defer rw.WriteHeader(http.StatusNotImplemented) // This is a NOP when a handler has already written and set the status
uri, err := r.URL()
uri, err = r.URL()
if err != nil {
d.logError("Error processing request, unable to get URL (HttpResponse=500)", "error", err.Error())
d.logError("Error processing request, unable to get URL: %s (HttpResponse=500)", err)
http.Error(rw, err.Error(), http.StatusInternalServerError)
return
}

View File

@ -0,0 +1,216 @@
//go:build windows
package webview
import (
"fmt"
"io"
"net/http"
"strings"
"github.com/wailsapp/go-webview2/pkg/edge"
)
// NewRequest creates as new WebViewRequest for chromium. This Method must be called from the Main-Thread!
func NewRequest(env *edge.ICoreWebView2Environment, args *edge.ICoreWebView2WebResourceRequestedEventArgs, invokeSync func(fn func())) (Request, error) {
req, err := args.GetRequest()
if err != nil {
return nil, fmt.Errorf("GetRequest failed: %s", err)
}
defer req.Release()
r := &request{
invokeSync: invokeSync,
}
code := http.StatusInternalServerError
r.response, err = env.CreateWebResourceResponse(nil, code, http.StatusText(code), "")
if err != nil {
return nil, fmt.Errorf("CreateWebResourceResponse failed: %s", err)
}
if err := args.PutResponse(r.response); err != nil {
r.finishResponse()
return nil, fmt.Errorf("PutResponse failed: %s", err)
}
r.deferral, err = args.GetDeferral()
if err != nil {
r.finishResponse()
return nil, fmt.Errorf("GetDeferral failed: %s", err)
}
r.url, r.urlErr = req.GetUri()
r.method, r.methodErr = req.GetMethod()
r.header, r.headerErr = getHeaders(req)
if content, err := req.GetContent(); err != nil {
r.bodyErr = err
} else if content != nil {
// It is safe to access Content from another Thread: https://learn.microsoft.com/en-us/microsoft-edge/webview2/concepts/threading-model#thread-safety
r.body = &iStreamReleaseCloser{stream: content}
}
return r, nil
}
var _ Request = &request{}
type request struct {
response *edge.ICoreWebView2WebResourceResponse
deferral *edge.ICoreWebView2Deferral
url string
urlErr error
method string
methodErr error
header http.Header
headerErr error
body io.ReadCloser
bodyErr error
rw *responseWriter
invokeSync func(fn func())
}
func (r *request) URL() (string, error) {
return r.url, r.urlErr
}
func (r *request) Method() (string, error) {
return r.method, r.methodErr
}
func (r *request) Header() (http.Header, error) {
return r.header, r.headerErr
}
func (r *request) Body() (io.ReadCloser, error) {
return r.body, r.bodyErr
}
func (r *request) Response() ResponseWriter {
if r.rw != nil {
return r.rw
}
r.rw = &responseWriter{req: r}
return r.rw
}
func (r *request) Close() error {
var errs []error
if r.body != nil {
if err := r.body.Close(); err != nil {
errs = append(errs, err)
}
r.body = nil
}
if err := r.Response().Finish(); err != nil {
errs = append(errs, err)
}
return combineErrs(errs)
}
// finishResponse must be called on the main-thread
func (r *request) finishResponse() error {
var errs []error
if r.response != nil {
if err := r.response.Release(); err != nil {
errs = append(errs, err)
}
r.response = nil
}
if r.deferral != nil {
if err := r.deferral.Complete(); err != nil {
errs = append(errs, err)
}
if err := r.deferral.Release(); err != nil {
errs = append(errs, err)
}
r.deferral = nil
}
return combineErrs(errs)
}
type iStreamReleaseCloser struct {
stream *edge.IStream
closed bool
}
func (i *iStreamReleaseCloser) Read(p []byte) (int, error) {
if i.closed {
return 0, io.ErrClosedPipe
}
return i.stream.Read(p)
}
func (i *iStreamReleaseCloser) Close() error {
if i.closed {
return nil
}
i.closed = true
return i.stream.Release()
}
func getHeaders(req *edge.ICoreWebView2WebResourceRequest) (http.Header, error) {
header := http.Header{}
headers, err := req.GetHeaders()
if err != nil {
return nil, fmt.Errorf("GetHeaders Error: %s", err)
}
defer headers.Release()
headersIt, err := headers.GetIterator()
if err != nil {
return nil, fmt.Errorf("GetIterator Error: %s", err)
}
defer headersIt.Release()
for {
has, err := headersIt.HasCurrentHeader()
if err != nil {
return nil, fmt.Errorf("HasCurrentHeader Error: %s", err)
}
if !has {
break
}
name, value, err := headersIt.GetCurrentHeader()
if err != nil {
return nil, fmt.Errorf("GetCurrentHeader Error: %s", err)
}
header.Set(name, value)
if _, err := headersIt.MoveNext(); err != nil {
return nil, fmt.Errorf("MoveNext Error: %s", err)
}
}
// 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")
return header, nil
}
func combineErrs(errs []error) error {
// TODO use Go1.20 errors.Join
if len(errs) == 0 {
return nil
}
errStrings := make([]string, len(errs))
for i, err := range errs {
errStrings[i] = err.Error()
}
return fmt.Errorf(strings.Join(errStrings, "\n"))
}

View File

@ -21,7 +21,7 @@ type ResponseWriter interface {
http.ResponseWriter
// Finish the response and flush all data. A Finish after the request has already been finished has no effect.
Finish()
Finish() error
// Code returns the HTTP status code of the response
Code() int

View File

@ -135,17 +135,19 @@ func (rw *responseWriter) WriteHeader(code int) {
C.URLSchemeTaskDidReceiveResponse(rw.r.task, C.int(code), headers, C.int(headersLen))
}
func (rw *responseWriter) Finish() {
func (rw *responseWriter) Finish() error {
if !rw.wroteHeader {
rw.WriteHeader(http.StatusNotImplemented)
}
if rw.finished {
return
return nil
}
rw.finished = true
C.URLSchemeTaskDidFinish(rw.r.task)
return nil
}
func (rw *responseWriter) Code() int {

View File

@ -1,5 +1,4 @@
//go:build linux
// +build linux
package webview
@ -90,18 +89,19 @@ func (rw *responseWriter) WriteHeader(code int) {
}
}
func (rw *responseWriter) Finish() {
func (rw *responseWriter) Finish() error {
if !rw.wroteHeader {
rw.WriteHeader(http.StatusNotImplemented)
}
if rw.finished {
return
return nil
}
rw.finished = true
if rw.w != nil {
rw.w.Close()
}
return nil
}
func (rw *responseWriter) finishWithError(code int, err error) {

View File

@ -0,0 +1,108 @@
//go:build windows
package webview
import (
"bytes"
"fmt"
"net/http"
"strings"
)
var _ http.ResponseWriter = &responseWriter{}
type responseWriter struct {
req *request
header http.Header
wroteHeader bool
code int
body *bytes.Buffer
finished bool
}
func (rw *responseWriter) Header() http.Header {
if rw.header == nil {
rw.header = http.Header{}
}
return rw.header
}
func (rw *responseWriter) Write(buf []byte) (int, error) {
if rw.finished {
return 0, errResponseFinished
}
rw.WriteHeader(http.StatusOK)
return rw.body.Write(buf)
}
func (rw *responseWriter) WriteHeader(code int) {
if rw.wroteHeader || rw.finished {
return
}
rw.wroteHeader = true
if rw.body == nil {
rw.body = &bytes.Buffer{}
}
rw.code = code
}
func (rw *responseWriter) Finish() error {
if !rw.wroteHeader {
rw.WriteHeader(http.StatusNotImplemented)
}
if rw.finished {
return nil
}
rw.finished = true
var errs []error
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.
errs = append(errs, fmt.Errorf("AssetServer returned 304 - StatusNotModified which are going to hang WebView2, changed code to 505 - StatusInternalServerError"))
code = http.StatusInternalServerError
}
rw.req.invokeSync(func() {
resp := rw.req.response
hdrs, err := resp.GetHeaders()
if err != nil {
errs = append(errs, fmt.Errorf("Resp.GetHeaders failed: %s", err))
} else {
for k, v := range rw.header {
if err := hdrs.AppendHeader(k, strings.Join(v, ",")); err != nil {
errs = append(errs, fmt.Errorf("Resp.AppendHeader failed: %s", err))
}
}
hdrs.Release()
}
if err := resp.PutStatusCode(code); err != nil {
errs = append(errs, fmt.Errorf("Resp.PutStatusCode failed: %s", err))
}
if err := resp.PutByteContent(rw.body.Bytes()); err != nil {
errs = append(errs, fmt.Errorf("Resp.PutByteContent failed: %s", err))
}
if err := rw.req.finishResponse(); err != nil {
errs = append(errs, fmt.Errorf("Resp.finishResponse failed: %s", err))
}
})
return combineErrs(errs)
}
func (rw *responseWriter) Code() int {
return rw.code
}

View File

@ -8,10 +8,10 @@ import (
"github.com/bep/debounce"
"github.com/wailsapp/go-webview2/webviewloader"
"github.com/wailsapp/wails/v3/internal/assetserver"
"github.com/wailsapp/wails/v3/internal/assetserver/webview"
"github.com/wailsapp/wails/v3/internal/capabilities"
"io"
"net/http"
"net/http/httptest"
"net/url"
"path"
"strconv"
@ -1306,13 +1306,7 @@ func (i *iStreamReleaseCloser) Close() error {
}
func (w *windowsWebviewWindow) processRequest(req *edge.ICoreWebView2WebResourceRequest, args *edge.ICoreWebView2WebResourceRequestedEventArgs) {
/*
webviewRequests <- &webViewAssetRequest{
Request: webview.NewRequest(wkUrlSchemeTask),
windowId: uint(windowID),
windowName: globalApplication.getWindowForID(uint(windowID)).Name(),
}
*/
// Setting the UserAgent on the CoreWebView2Settings clears the whole default UserAgent of the Edge browser, but
// we want to just append our ApplicationIdentifier. So we adjust the UserAgent for every request.
if reqHeaders, err := req.GetHeaders(); err == nil {
@ -1344,36 +1338,23 @@ func (w *windowsWebviewWindow) processRequest(req *edge.ICoreWebView2WebResource
return
}
rw := httptest.NewRecorder()
globalApplication.assets.ProcessHTTPRequestLegacy(rw, coreWebview2RequestToHttpRequest(req))
headers := []string{}
for k, v := range rw.Header() {
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.
globalApplication.error("AssetServer returned 304 - StatusNotModified which is going to hang WebView2, changed code to 505 - StatusInternalServerError", "uri", uri)
code = http.StatusInternalServerError
}
env := w.chromium.Environment()
response, err := env.CreateWebResourceResponse(rw.Body.Bytes(), code, http.StatusText(code), strings.Join(headers, "\n"))
webviewRequest, err := webview.NewRequest(
w.chromium.Environment(),
args,
func(fn func()) {
InvokeSync(fn)
})
if err != nil {
globalApplication.error("CreateWebResourceResponse Error: " + err.Error())
globalApplication.error("%s: NewRequest failed: %s", uri, err)
return
}
defer response.Release()
// Send response back
err = args.PutResponse(response)
if err != nil {
globalApplication.error("PutResponse Error: " + err.Error())
return
webviewRequests <- &webViewAssetRequest{
Request: webviewRequest,
windowId: uint(windowID),
windowName: globalApplication.getWindowForID(uint(windowID)).Name(),
}
//globalApplication.assets.ServeWebViewRequest(webviewRequest)
}
func (w *windowsWebviewWindow) setupChromium() {