mirror of
https://github.com/wavetermdev/wails.git
synced 2026-08-05 13:53:43 -07:00
[assetServer] Improve release/close handling of webview requests (#2612)
This commit is contained in:
@@ -13,6 +13,5 @@ type Request interface {
|
||||
|
||||
Response() ResponseWriter
|
||||
|
||||
AddRef() error
|
||||
Release() error
|
||||
Close() error
|
||||
}
|
||||
|
||||
@@ -118,11 +118,9 @@ import (
|
||||
)
|
||||
|
||||
// NewRequest creates as new WebViewRequest based on a pointer to an `id<WKURLSchemeTask>`
|
||||
//
|
||||
// Please make sure to call Release() when finished using the request.
|
||||
func NewRequest(wkURLSchemeTask unsafe.Pointer) Request {
|
||||
C.URLSchemeTaskRetain(wkURLSchemeTask)
|
||||
return &request{task: wkURLSchemeTask}
|
||||
return newRequestFinalizer(&request{task: wkURLSchemeTask})
|
||||
}
|
||||
|
||||
var _ Request = &request{}
|
||||
@@ -135,16 +133,6 @@ type request struct {
|
||||
rw *responseWriter
|
||||
}
|
||||
|
||||
func (r *request) AddRef() error {
|
||||
C.URLSchemeTaskRetain(r.task)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *request) Release() error {
|
||||
C.URLSchemeTaskRelease(r.task)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *request) URL() (string, error) {
|
||||
return C.GoString(C.URLSchemeTaskRequestURL(r.task)), nil
|
||||
}
|
||||
@@ -205,6 +193,16 @@ func (r *request) Response() ResponseWriter {
|
||||
return r.rw
|
||||
}
|
||||
|
||||
func (r *request) Close() error {
|
||||
var err error
|
||||
if r.body != nil {
|
||||
err = r.body.Close()
|
||||
}
|
||||
r.Response().Finish()
|
||||
C.URLSchemeTaskRelease(r.task)
|
||||
return err
|
||||
}
|
||||
|
||||
var _ io.ReadCloser = &requestBodyStreamReader{}
|
||||
|
||||
type requestBodyStreamReader struct {
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
package webview
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
"sync/atomic"
|
||||
)
|
||||
|
||||
var _ Request = &requestFinalizer{}
|
||||
|
||||
type requestFinalizer struct {
|
||||
Request
|
||||
closed int32
|
||||
}
|
||||
|
||||
// newRequestFinalizer returns a request with a runtime finalizer to make sure it will be closed from the finalizer
|
||||
// if it has not been already closed.
|
||||
// It also makes sure Close() of the wrapping request is only called once.
|
||||
func newRequestFinalizer(r Request) Request {
|
||||
rf := &requestFinalizer{Request: r}
|
||||
// Make sure to async release since it might block the finalizer goroutine for a longer period
|
||||
runtime.SetFinalizer(rf, func(obj *requestFinalizer) { rf.close(true) })
|
||||
return rf
|
||||
}
|
||||
|
||||
func (r *requestFinalizer) Close() error {
|
||||
return r.close(false)
|
||||
}
|
||||
|
||||
func (r *requestFinalizer) close(asyncRelease bool) error {
|
||||
if atomic.CompareAndSwapInt32(&r.closed, 0, 1) {
|
||||
runtime.SetFinalizer(r, nil)
|
||||
if asyncRelease {
|
||||
go r.Request.Close()
|
||||
return nil
|
||||
} else {
|
||||
return r.Request.Close()
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -18,13 +18,12 @@ import (
|
||||
)
|
||||
|
||||
// NewRequest creates as new WebViewRequest based on a pointer to an `WebKitURISchemeRequest`
|
||||
//
|
||||
// Please make sure to call Release() when finished using the request.
|
||||
func NewRequest(webKitURISchemeRequest unsafe.Pointer) Request {
|
||||
webkitReq := (*C.WebKitURISchemeRequest)(webKitURISchemeRequest)
|
||||
C.g_object_ref(C.gpointer(webkitReq))
|
||||
|
||||
req := &request{req: webkitReq}
|
||||
req.AddRef()
|
||||
return req
|
||||
return newRequestFinalizer(req)
|
||||
}
|
||||
|
||||
var _ Request = &request{}
|
||||
@@ -37,16 +36,6 @@ type request struct {
|
||||
rw *responseWriter
|
||||
}
|
||||
|
||||
func (r *request) AddRef() error {
|
||||
C.g_object_ref(C.gpointer(r.req))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *request) Release() error {
|
||||
C.g_object_unref(C.gpointer(r.req))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *request) URL() (string, error) {
|
||||
return C.GoString(C.webkit_uri_scheme_request_get_uri(r.req)), nil
|
||||
}
|
||||
@@ -82,3 +71,13 @@ func (r *request) Response() ResponseWriter {
|
||||
r.rw = &responseWriter{req: r.req}
|
||||
return r.rw
|
||||
}
|
||||
|
||||
func (r *request) Close() error {
|
||||
var err error
|
||||
if r.body != nil {
|
||||
err = r.body.Close()
|
||||
}
|
||||
r.Response().Finish()
|
||||
C.g_object_unref(C.gpointer(r.req))
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -20,6 +20,6 @@ var (
|
||||
type ResponseWriter interface {
|
||||
http.ResponseWriter
|
||||
|
||||
// Finish the response and flush all data.
|
||||
Finish() error
|
||||
// Finish the response and flush all data. A Finish after the request has already been finished has no effect.
|
||||
Finish()
|
||||
}
|
||||
|
||||
@@ -133,16 +133,15 @@ func (rw *responseWriter) WriteHeader(code int) {
|
||||
C.URLSchemeTaskDidReceiveResponse(rw.r.task, C.int(code), headers, C.int(headersLen))
|
||||
}
|
||||
|
||||
func (rw *responseWriter) Finish() error {
|
||||
func (rw *responseWriter) Finish() {
|
||||
if !rw.wroteHeader {
|
||||
rw.WriteHeader(http.StatusNotImplemented)
|
||||
}
|
||||
|
||||
if rw.finished {
|
||||
return nil
|
||||
return
|
||||
}
|
||||
rw.finished = true
|
||||
|
||||
C.URLSchemeTaskDidFinish(rw.r.task)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -84,19 +84,18 @@ func (rw *responseWriter) WriteHeader(code int) {
|
||||
}
|
||||
}
|
||||
|
||||
func (rw *responseWriter) Finish() error {
|
||||
func (rw *responseWriter) Finish() {
|
||||
if !rw.wroteHeader {
|
||||
rw.WriteHeader(http.StatusNotImplemented)
|
||||
}
|
||||
|
||||
if rw.finished {
|
||||
return nil
|
||||
return
|
||||
}
|
||||
rw.finished = true
|
||||
if rw.w != nil {
|
||||
rw.w.Close()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (rw *responseWriter) finishWithError(code int, err error) {
|
||||
|
||||
Reference in New Issue
Block a user