[assetserver, linux] Add support for WebKit2GTK 2.40+ features (#2592)

This commit is contained in:
stffabi
2023-04-14 11:16:27 +02:00
committed by GitHub
parent ec3da8b7ef
commit 39a7ab5856
8 changed files with 173 additions and 60 deletions
+1 -2
View File
@@ -69,8 +69,7 @@ func (r *request) Body() (io.ReadCloser, error) {
return r.body, nil
}
// WebKit2GTK has currently no support for request bodies.
r.body = http.NoBody
r.body = webkit_uri_scheme_request_get_http_body(r.req)
return r.body, nil
}
+69
View File
@@ -0,0 +1,69 @@
//go:build linux && (webkit2_36 || webkit2_40)
package webview
/*
#cgo linux pkg-config: gtk+-3.0 webkit2gtk-4.0 libsoup-2.4
#include "gtk/gtk.h"
#include "webkit2/webkit2.h"
#include "libsoup/soup.h"
*/
import "C"
import (
"net/http"
"strings"
"unsafe"
)
func webkit_uri_scheme_request_get_http_method(req *C.WebKitURISchemeRequest) string {
method := C.GoString(C.webkit_uri_scheme_request_get_http_method(req))
return strings.ToUpper(method)
}
func webkit_uri_scheme_request_get_http_headers(req *C.WebKitURISchemeRequest) http.Header {
hdrs := C.webkit_uri_scheme_request_get_http_headers(req)
var iter C.SoupMessageHeadersIter
C.soup_message_headers_iter_init(&iter, hdrs)
var name *C.char
var value *C.char
h := http.Header{}
for C.soup_message_headers_iter_next(&iter, &name, &value) != 0 {
h.Add(C.GoString(name), C.GoString(value))
}
return h
}
func webkit_uri_scheme_request_finish(req *C.WebKitURISchemeRequest, code int, header http.Header, stream *C.GInputStream, streamLength int64) error {
resp := C.webkit_uri_scheme_response_new(stream, C.gint64(streamLength))
defer C.g_object_unref(C.gpointer(resp))
cReason := C.CString(http.StatusText(code))
C.webkit_uri_scheme_response_set_status(resp, C.guint(code), cReason)
C.free(unsafe.Pointer(cReason))
cMimeType := C.CString(header.Get(HeaderContentType))
C.webkit_uri_scheme_response_set_content_type(resp, cMimeType)
C.free(unsafe.Pointer(cMimeType))
hdrs := C.soup_message_headers_new(C.SOUP_MESSAGE_HEADERS_RESPONSE)
for name, values := range header {
cName := C.CString(name)
for _, value := range values {
cValue := C.CString(value)
C.soup_message_headers_append(hdrs, cName, cValue)
C.free(unsafe.Pointer(cValue))
}
C.free(unsafe.Pointer(cName))
}
C.webkit_uri_scheme_response_set_http_headers(resp, hdrs)
C.webkit_uri_scheme_request_finish_with_response(req, resp)
return nil
}
+4 -54
View File
@@ -3,69 +3,19 @@
package webview
/*
#cgo linux pkg-config: gtk+-3.0 webkit2gtk-4.0 libsoup-2.4
#cgo linux pkg-config: webkit2gtk-4.0
#include "gtk/gtk.h"
#include "webkit2/webkit2.h"
#include "libsoup/soup.h"
*/
import "C"
import (
"io"
"net/http"
"strings"
"unsafe"
)
const Webkit2MinMinorVersion = 36
func webkit_uri_scheme_request_get_http_method(req *C.WebKitURISchemeRequest) string {
method := C.GoString(C.webkit_uri_scheme_request_get_http_method(req))
return strings.ToUpper(method)
}
func webkit_uri_scheme_request_get_http_headers(req *C.WebKitURISchemeRequest) http.Header {
hdrs := C.webkit_uri_scheme_request_get_http_headers(req)
var iter C.SoupMessageHeadersIter
C.soup_message_headers_iter_init(&iter, hdrs)
var name *C.char
var value *C.char
h := http.Header{}
for C.soup_message_headers_iter_next(&iter, &name, &value) != 0 {
h.Add(C.GoString(name), C.GoString(value))
}
return h
}
func webkit_uri_scheme_request_finish(req *C.WebKitURISchemeRequest, code int, header http.Header, stream *C.GInputStream, streamLength int64) error {
resp := C.webkit_uri_scheme_response_new(stream, C.gint64(streamLength))
defer C.g_object_unref(C.gpointer(resp))
cReason := C.CString(http.StatusText(code))
C.webkit_uri_scheme_response_set_status(resp, C.guint(code), cReason)
C.free(unsafe.Pointer(cReason))
cMimeType := C.CString(header.Get(HeaderContentType))
C.webkit_uri_scheme_response_set_content_type(resp, cMimeType)
C.free(unsafe.Pointer(cMimeType))
hdrs := C.soup_message_headers_new(C.SOUP_MESSAGE_HEADERS_RESPONSE)
for name, values := range header {
cName := C.CString(name)
for _, value := range values {
cValue := C.CString(value)
C.soup_message_headers_append(hdrs, cName, cValue)
C.free(unsafe.Pointer(cValue))
}
C.free(unsafe.Pointer(cName))
}
C.webkit_uri_scheme_response_set_http_headers(resp, hdrs)
C.webkit_uri_scheme_request_finish_with_response(req, resp)
return nil
func webkit_uri_scheme_request_get_http_body(_ *C.WebKitURISchemeRequest) io.ReadCloser {
return http.NoBody
}
+83
View File
@@ -0,0 +1,83 @@
//go:build linux && webkit2_40
package webview
/*
#cgo linux pkg-config: gtk+-3.0 webkit2gtk-4.0 gio-unix-2.0
#include "gtk/gtk.h"
#include "webkit2/webkit2.h"
#include "gio/gunixinputstream.h"
*/
import "C"
import (
"fmt"
"io"
"net/http"
"unsafe"
)
func webkit_uri_scheme_request_get_http_body(req *C.WebKitURISchemeRequest) io.ReadCloser {
stream := C.webkit_uri_scheme_request_get_http_body(req)
if stream == nil {
return http.NoBody
}
return &webkitRequestBody{stream: stream}
}
type webkitRequestBody struct {
stream *C.GInputStream
closed bool
}
// Read implements io.Reader
func (r *webkitRequestBody) Read(p []byte) (int, error) {
if r.closed {
return 0, io.ErrClosedPipe
}
var content unsafe.Pointer
var contentLen int
if p != nil {
content = unsafe.Pointer(&p[0])
contentLen = len(p)
}
var n C.gsize
var gErr *C.GError
res := C.g_input_stream_read_all(r.stream, content, C.gsize(contentLen), &n, nil, &gErr)
if res == 0 {
return 0, formatGError("stream read failed", gErr)
} else if n == 0 {
return 0, io.EOF
}
return int(n), nil
}
func (r *webkitRequestBody) Close() error {
if r.closed {
return nil
}
r.closed = true
// https://docs.gtk.org/gio/method.InputStream.close.html
// Streams will be automatically closed when the last reference is dropped, but you might want to call this function
// to make sure resources are released as early as possible.
var err error
var gErr *C.GError
if C.g_input_stream_close(r.stream, nil, &gErr) == 0 {
err = formatGError("stream close failed", gErr)
}
C.g_object_unref(C.gpointer(r.stream))
r.stream = nil
return err
}
func formatGError(msg string, gErr *C.GError, args ...any) error {
if gErr != nil && gErr.message != nil {
msg += ": " + C.GoString(gErr.message)
C.g_error_free(gErr)
}
return fmt.Errorf(msg, args...)
}
+5
View File
@@ -0,0 +1,5 @@
//go:build linux && webkit2_40
package webview
const Webkit2MinMinorVersion = 40
+6 -1
View File
@@ -1,4 +1,4 @@
//go:build linux && !webkit2_36
//go:build linux && !(webkit2_36 || webkit2_40)
package webview
@@ -12,6 +12,7 @@ import "C"
import (
"fmt"
"io"
"net/http"
"unsafe"
)
@@ -26,6 +27,10 @@ func webkit_uri_scheme_request_get_http_headers(_ *C.WebKitURISchemeRequest) htt
return http.Header{}
}
func webkit_uri_scheme_request_get_http_body(_ *C.WebKitURISchemeRequest) io.ReadCloser {
return http.NoBody
}
func webkit_uri_scheme_request_finish(req *C.WebKitURISchemeRequest, code int, header http.Header, stream *C.GInputStream, streamLength int64) error {
if code != http.StatusOK {
return fmt.Errorf("StatusCodes not supported: %d - %s", code, http.StatusText(code))
+4 -3
View File
@@ -260,8 +260,8 @@ Not all features of an `http.Request` are currently supported, please see the fo
| PATCH | ✅ | ✅ | ✅ [^1] |
| DELETE | ✅ | ✅ | ✅ [^1] |
| Request Headers | ✅ | ✅ | ✅ [^1] |
| Request Body | ✅ | ✅ | |
| Request Body Streaming | ✅ | ✅ | |
| Request Body | ✅ | ✅ | ✅ [^2] |
| Request Body Streaming | ✅ | ✅ | ✅ [^2] |
| Response StatusCodes | ✅ | ✅ | ✅ [^1] |
| Response Headers | ✅ | ✅ | ✅ [^1] |
| Response Body | ✅ | ✅ | ✅ |
@@ -269,7 +269,8 @@ Not all features of an `http.Request` are currently supported, please see the fo
| WebSockets | ❌ | ❌ | ❌ |
| HTTP Redirects 30x | ✅ | ❌ | ❌ |
[^1]: This requires WebKit2GTK 2.36+ support and your app needs to be build with the build tag `webkit2_36` to activate support for this feature. This also bumps the minimum requirement of WebKit2GTK to 2.36 for your app.
[^1]: This requires WebKit2GTK 2.36+ support and your app needs to be build with the build tag `webkit2_36` to activate support for this feature. This also bumps the minimum requirement of WebKit2GTK to 2.36 for your app.
[^2]: This requires WebKit2GTK 2.40+ support and your app needs to be build with the build tag `webkit2_40` to activate support for this feature. This also bumps the minimum requirement of WebKit2GTK to 2.40 for your app.
Name: AssetServer<br/>
Type: `*assetserver.Options`
+1
View File
@@ -17,6 +17,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- Added Nodejs version in `wails doctor`. Added by @misitebao in [PR](https://github.com/wailsapp/wails/pull/2546)
- Added support for WebKit2GTK 2.40+ on Linux. This brings additional features for the [AssetServer](/docs/reference/options#assetserver), like support for HTTP Request Bodies. The app must be compiled with the Go build tag `webkit2_40` to activate support for this features. This also bumps the minimum requirement of WebKit2GTK to 2.40 for your app. Added by @stffabi in this [PR](https://github.com/wailsapp/wails/pull/2592)
### Changed