mirror of
https://github.com/wailsapp/wails.git
synced 2025-05-03 03:52:41 +08:00
[assetserver] Add linux platform implementation (#2543)
This commit is contained in:
parent
eb36258c73
commit
db527c0fc2
@ -78,7 +78,6 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"runtime"
|
"runtime"
|
||||||
@ -88,6 +87,7 @@ import (
|
|||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"github.com/wailsapp/wails/v2/pkg/assetserver"
|
"github.com/wailsapp/wails/v2/pkg/assetserver"
|
||||||
|
"github.com/wailsapp/wails/v2/pkg/assetserver/webview"
|
||||||
|
|
||||||
"github.com/wailsapp/wails/v2/internal/binding"
|
"github.com/wailsapp/wails/v2/internal/binding"
|
||||||
"github.com/wailsapp/wails/v2/internal/frontend"
|
"github.com/wailsapp/wails/v2/internal/frontend"
|
||||||
@ -166,11 +166,8 @@ func NewFrontend(ctx context.Context, appoptions *options.App, myLogger *logger.
|
|||||||
}
|
}
|
||||||
result.assets = assets
|
result.assets = assets
|
||||||
|
|
||||||
// Start 10 processors to handle requests in parallel
|
|
||||||
for i := 0; i < 10; i++ {
|
|
||||||
go result.startRequestProcessor()
|
go result.startRequestProcessor()
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
go result.startMessageProcessor()
|
go result.startMessageProcessor()
|
||||||
|
|
||||||
@ -461,50 +458,16 @@ func processMessage(message *C.char) {
|
|||||||
messageBuffer <- goMessage
|
messageBuffer <- goMessage
|
||||||
}
|
}
|
||||||
|
|
||||||
var requestBuffer = make(chan unsafe.Pointer, 100)
|
var requestBuffer = make(chan webview.Request, 100)
|
||||||
|
|
||||||
func (f *Frontend) startRequestProcessor() {
|
func (f *Frontend) startRequestProcessor() {
|
||||||
for request := range requestBuffer {
|
for request := range requestBuffer {
|
||||||
f.processRequest(request)
|
f.assets.ServeWebViewRequest(request)
|
||||||
C.g_object_unref(C.gpointer(request))
|
request.Release()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//export processURLRequest
|
//export processURLRequest
|
||||||
func processURLRequest(request unsafe.Pointer) {
|
func processURLRequest(request unsafe.Pointer) {
|
||||||
// Increment reference counter to allow async processing, will be decremented after the processing
|
requestBuffer <- webview.NewRequest(request)
|
||||||
// has been finished by a worker.
|
|
||||||
C.g_object_ref(C.gpointer(request))
|
|
||||||
requestBuffer <- request
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *Frontend) processRequest(request unsafe.Pointer) {
|
|
||||||
req := (*C.WebKitURISchemeRequest)(request)
|
|
||||||
uri := C.webkit_uri_scheme_request_get_uri(req)
|
|
||||||
goURI := C.GoString(uri)
|
|
||||||
|
|
||||||
rw := &webKitResponseWriter{req: req}
|
|
||||||
defer rw.Close()
|
|
||||||
|
|
||||||
f.assets.ProcessHTTPRequestLegacy(
|
|
||||||
rw,
|
|
||||||
func() (*http.Request, error) {
|
|
||||||
method := webkit_uri_scheme_request_get_http_method(req)
|
|
||||||
r, err := http.NewRequest(method, goURI, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
r.Header = webkit_uri_scheme_request_get_http_headers(req)
|
|
||||||
|
|
||||||
if r.URL.Host != f.startURL.Host {
|
|
||||||
if r.Body != nil {
|
|
||||||
r.Body.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, fmt.Errorf("Expected host '%s' in request, but was '%s'", f.startURL.Host, r.URL.Host)
|
|
||||||
}
|
|
||||||
|
|
||||||
return r, nil
|
|
||||||
})
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -12,10 +12,12 @@ import (
|
|||||||
|
|
||||||
"github.com/wailsapp/wails/v2/pkg/options"
|
"github.com/wailsapp/wails/v2/pkg/options"
|
||||||
"github.com/wailsapp/wails/v2/pkg/options/linux"
|
"github.com/wailsapp/wails/v2/pkg/options/linux"
|
||||||
|
|
||||||
|
"github.com/wailsapp/wails/v2/pkg/assetserver/webview"
|
||||||
)
|
)
|
||||||
|
|
||||||
func validateWebKit2Version(options *options.App) {
|
func validateWebKit2Version(options *options.App) {
|
||||||
if C.webkit_get_major_version() == 2 && C.webkit_get_minor_version() >= webkit2MinMinorVersion {
|
if C.webkit_get_major_version() == 2 && C.webkit_get_minor_version() >= webview.Webkit2MinMinorVersion {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -24,6 +26,6 @@ func validateWebKit2Version(options *options.App) {
|
|||||||
msg = options.Linux.Messages
|
msg = options.Linux.Messages
|
||||||
}
|
}
|
||||||
|
|
||||||
v := fmt.Sprintf("2.%d.0", webkit2MinMinorVersion)
|
v := fmt.Sprintf("2.%d.0", webview.Webkit2MinMinorVersion)
|
||||||
showModalDialogAndExit("WebKit2GTK", fmt.Sprintf(msg.WebKit2GTKMinRequired, v))
|
showModalDialogAndExit("WebKit2GTK", fmt.Sprintf(msg.WebKit2GTKMinRequired, v))
|
||||||
}
|
}
|
||||||
|
85
v2/pkg/assetserver/webview/request_linux.go
Normal file
85
v2/pkg/assetserver/webview/request_linux.go
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
//go:build linux
|
||||||
|
// +build linux
|
||||||
|
|
||||||
|
package webview
|
||||||
|
|
||||||
|
/*
|
||||||
|
#cgo linux pkg-config: gtk+-3.0 webkit2gtk-4.0 gio-unix-2.0
|
||||||
|
|
||||||
|
#include "gtk/gtk.h"
|
||||||
|
#include "webkit2/webkit2.h"
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
req := &request{req: webkitReq}
|
||||||
|
req.AddRef()
|
||||||
|
return req
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ Request = &request{}
|
||||||
|
|
||||||
|
type request struct {
|
||||||
|
req *C.WebKitURISchemeRequest
|
||||||
|
|
||||||
|
header http.Header
|
||||||
|
body io.ReadCloser
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *request) Method() (string, error) {
|
||||||
|
return webkit_uri_scheme_request_get_http_method(r.req), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *request) Header() (http.Header, error) {
|
||||||
|
if r.header != nil {
|
||||||
|
return r.header, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
r.header = webkit_uri_scheme_request_get_http_headers(r.req)
|
||||||
|
return r.header, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *request) Body() (io.ReadCloser, error) {
|
||||||
|
if r.body != nil {
|
||||||
|
return r.body, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// WebKit2GTK has currently no support for request bodies.
|
||||||
|
r.body = http.NoBody
|
||||||
|
|
||||||
|
return r.body, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *request) Response() ResponseWriter {
|
||||||
|
if r.rw != nil {
|
||||||
|
return r.rw
|
||||||
|
}
|
||||||
|
|
||||||
|
r.rw = &responseWriter{req: r.req}
|
||||||
|
return r.rw
|
||||||
|
}
|
@ -1,9 +1,20 @@
|
|||||||
package webview
|
package webview
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
HeaderContentLength = "Content-Length"
|
||||||
|
HeaderContentType = "Content-Type"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
errRequestStopped = errors.New("request has been stopped")
|
||||||
|
errResponseFinished = errors.New("response has been finished")
|
||||||
|
)
|
||||||
|
|
||||||
// A ResponseWriter interface is used by an HTTP handler to
|
// A ResponseWriter interface is used by an HTTP handler to
|
||||||
// construct an HTTP response for the WebView.
|
// construct an HTTP response for the WebView.
|
||||||
type ResponseWriter interface {
|
type ResponseWriter interface {
|
||||||
|
@ -69,16 +69,10 @@ import "C"
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
|
||||||
errRequestStopped = errors.New("request has been stopped")
|
|
||||||
errResponseFinished = errors.New("response has been finished")
|
|
||||||
)
|
|
||||||
|
|
||||||
var _ ResponseWriter = &responseWriter{}
|
var _ ResponseWriter = &responseWriter{}
|
||||||
|
|
||||||
type responseWriter struct {
|
type responseWriter struct {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
//go:build linux
|
//go:build linux
|
||||||
// +build linux
|
// +build linux
|
||||||
|
|
||||||
package linux
|
package webview
|
||||||
|
|
||||||
/*
|
/*
|
||||||
#cgo linux pkg-config: gtk+-3.0 webkit2gtk-4.0 gio-unix-2.0
|
#cgo linux pkg-config: gtk+-3.0 webkit2gtk-4.0 gio-unix-2.0
|
||||||
@ -20,28 +20,31 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"syscall"
|
"syscall"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"github.com/wailsapp/wails/v2/pkg/assetserver"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type webKitResponseWriter struct {
|
type responseWriter struct {
|
||||||
req *C.WebKitURISchemeRequest
|
req *C.WebKitURISchemeRequest
|
||||||
|
|
||||||
header http.Header
|
header http.Header
|
||||||
wroteHeader bool
|
wroteHeader bool
|
||||||
|
finished bool
|
||||||
|
|
||||||
w io.WriteCloser
|
w io.WriteCloser
|
||||||
wErr error
|
wErr error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rw *webKitResponseWriter) Header() http.Header {
|
func (rw *responseWriter) Header() http.Header {
|
||||||
if rw.header == nil {
|
if rw.header == nil {
|
||||||
rw.header = http.Header{}
|
rw.header = http.Header{}
|
||||||
}
|
}
|
||||||
return rw.header
|
return rw.header
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rw *webKitResponseWriter) Write(buf []byte) (int, error) {
|
func (rw *responseWriter) Write(buf []byte) (int, error) {
|
||||||
|
if rw.finished {
|
||||||
|
return 0, errResponseFinished
|
||||||
|
}
|
||||||
|
|
||||||
rw.WriteHeader(http.StatusOK)
|
rw.WriteHeader(http.StatusOK)
|
||||||
if rw.wErr != nil {
|
if rw.wErr != nil {
|
||||||
return 0, rw.wErr
|
return 0, rw.wErr
|
||||||
@ -49,14 +52,14 @@ func (rw *webKitResponseWriter) Write(buf []byte) (int, error) {
|
|||||||
return rw.w.Write(buf)
|
return rw.w.Write(buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rw *webKitResponseWriter) WriteHeader(code int) {
|
func (rw *responseWriter) WriteHeader(code int) {
|
||||||
if rw.wroteHeader {
|
if rw.wroteHeader || rw.finished {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
rw.wroteHeader = true
|
rw.wroteHeader = true
|
||||||
|
|
||||||
contentLength := int64(-1)
|
contentLength := int64(-1)
|
||||||
if sLen := rw.Header().Get(assetserver.HeaderContentLength); sLen != "" {
|
if sLen := rw.Header().Get(HeaderContentLength); sLen != "" {
|
||||||
if pLen, _ := strconv.ParseInt(sLen, 10, 64); pLen > 0 {
|
if pLen, _ := strconv.ParseInt(sLen, 10, 64); pLen > 0 {
|
||||||
contentLength = pLen
|
contentLength = pLen
|
||||||
}
|
}
|
||||||
@ -72,7 +75,7 @@ func (rw *webKitResponseWriter) WriteHeader(code int) {
|
|||||||
}
|
}
|
||||||
rw.w = w
|
rw.w = w
|
||||||
|
|
||||||
stream := C.g_unix_input_stream_new(C.int(rFD), gtkBool(true))
|
stream := C.g_unix_input_stream_new(C.int(rFD), C.gboolean(1))
|
||||||
defer C.g_object_unref(C.gpointer(stream))
|
defer C.g_object_unref(C.gpointer(stream))
|
||||||
|
|
||||||
if err := webkit_uri_scheme_request_finish(rw.req, code, rw.Header(), stream, contentLength); err != nil {
|
if err := webkit_uri_scheme_request_finish(rw.req, code, rw.Header(), stream, contentLength); err != nil {
|
||||||
@ -81,13 +84,22 @@ func (rw *webKitResponseWriter) WriteHeader(code int) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rw *webKitResponseWriter) Close() {
|
func (rw *responseWriter) Finish() error {
|
||||||
|
if !rw.wroteHeader {
|
||||||
|
rw.WriteHeader(http.StatusNotImplemented)
|
||||||
|
}
|
||||||
|
|
||||||
|
if rw.finished {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
rw.finished = true
|
||||||
if rw.w != nil {
|
if rw.w != nil {
|
||||||
rw.w.Close()
|
rw.w.Close()
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rw *webKitResponseWriter) finishWithError(code int, err error) {
|
func (rw *responseWriter) finishWithError(code int, err error) {
|
||||||
if rw.w != nil {
|
if rw.w != nil {
|
||||||
rw.w.Close()
|
rw.w.Close()
|
||||||
rw.w = &nopCloser{io.Discard}
|
rw.w = &nopCloser{io.Discard}
|
@ -1,6 +1,6 @@
|
|||||||
//go:build linux && webkit2_36
|
//go:build linux && webkit2_36
|
||||||
|
|
||||||
package linux
|
package webview
|
||||||
|
|
||||||
/*
|
/*
|
||||||
#cgo linux pkg-config: gtk+-3.0 webkit2gtk-4.0 libsoup-2.4
|
#cgo linux pkg-config: gtk+-3.0 webkit2gtk-4.0 libsoup-2.4
|
||||||
@ -15,11 +15,9 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"github.com/wailsapp/wails/v2/pkg/assetserver"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const webkit2MinMinorVersion = 36
|
const Webkit2MinMinorVersion = 36
|
||||||
|
|
||||||
func webkit_uri_scheme_request_get_http_method(req *C.WebKitURISchemeRequest) string {
|
func webkit_uri_scheme_request_get_http_method(req *C.WebKitURISchemeRequest) string {
|
||||||
method := C.GoString(C.webkit_uri_scheme_request_get_http_method(req))
|
method := C.GoString(C.webkit_uri_scheme_request_get_http_method(req))
|
||||||
@ -51,7 +49,7 @@ func webkit_uri_scheme_request_finish(req *C.WebKitURISchemeRequest, code int, h
|
|||||||
C.webkit_uri_scheme_response_set_status(resp, C.guint(code), cReason)
|
C.webkit_uri_scheme_response_set_status(resp, C.guint(code), cReason)
|
||||||
C.free(unsafe.Pointer(cReason))
|
C.free(unsafe.Pointer(cReason))
|
||||||
|
|
||||||
cMimeType := C.CString(header.Get(assetserver.HeaderContentType))
|
cMimeType := C.CString(header.Get(HeaderContentType))
|
||||||
C.webkit_uri_scheme_response_set_content_type(resp, cMimeType)
|
C.webkit_uri_scheme_response_set_content_type(resp, cMimeType)
|
||||||
C.free(unsafe.Pointer(cMimeType))
|
C.free(unsafe.Pointer(cMimeType))
|
||||||
|
|
@ -1,6 +1,6 @@
|
|||||||
//go:build linux && !webkit2_36
|
//go:build linux && !webkit2_36
|
||||||
|
|
||||||
package linux
|
package webview
|
||||||
|
|
||||||
/*
|
/*
|
||||||
#cgo linux pkg-config: gtk+-3.0 webkit2gtk-4.0
|
#cgo linux pkg-config: gtk+-3.0 webkit2gtk-4.0
|
||||||
@ -14,11 +14,9 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"github.com/wailsapp/wails/v2/pkg/assetserver"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const webkit2MinMinorVersion = 0
|
const Webkit2MinMinorVersion = 0
|
||||||
|
|
||||||
func webkit_uri_scheme_request_get_http_method(_ *C.WebKitURISchemeRequest) string {
|
func webkit_uri_scheme_request_get_http_method(_ *C.WebKitURISchemeRequest) string {
|
||||||
return http.MethodGet
|
return http.MethodGet
|
||||||
@ -33,7 +31,7 @@ func webkit_uri_scheme_request_finish(req *C.WebKitURISchemeRequest, code int, h
|
|||||||
return fmt.Errorf("StatusCodes not supported: %d - %s", code, http.StatusText(code))
|
return fmt.Errorf("StatusCodes not supported: %d - %s", code, http.StatusText(code))
|
||||||
}
|
}
|
||||||
|
|
||||||
cMimeType := C.CString(header.Get(assetserver.HeaderContentType))
|
cMimeType := C.CString(header.Get(HeaderContentType))
|
||||||
C.webkit_uri_scheme_request_finish(req, stream, C.gint64(streamLength), cMimeType)
|
C.webkit_uri_scheme_request_finish(req, stream, C.gint64(streamLength), cMimeType)
|
||||||
C.free(unsafe.Pointer(cMimeType))
|
C.free(unsafe.Pointer(cMimeType))
|
||||||
return nil
|
return nil
|
Loading…
Reference in New Issue
Block a user