mirror of
https://github.com/wailsapp/wails.git
synced 2025-05-08 05:11:50 +08:00
159 lines
4.2 KiB
Go
159 lines
4.2 KiB
Go
//go:build linux && purego
|
|
|
|
package webview
|
|
|
|
import (
|
|
"net/http"
|
|
"strings"
|
|
|
|
"github.com/ebitengine/purego"
|
|
)
|
|
|
|
func webkit_uri_scheme_request_get_http_method(req uintptr) string {
|
|
var getMethod func(uintptr) string
|
|
purego.RegisterLibFunc(&getMethod, gtk, "webkit_uri_scheme_request_get_http_method")
|
|
return strings.ToUpper(getMethod(req))
|
|
}
|
|
|
|
func webkit_uri_scheme_request_get_http_headers(req uintptr) http.Header {
|
|
var getHeaders func(uintptr) uintptr
|
|
purego.RegisterLibFunc(&getUri, webkit, "webkit_uri_scheme_request_get_http_headers")
|
|
|
|
hdrs := getHeaders(req)
|
|
|
|
var headersIterInit func(uintptr, uintptr) uintptr
|
|
purego.RegisterLibFunc(&headersIterInit, gtk, "soup_message_headers_iter_init")
|
|
|
|
// TODO: How do we get a struct?
|
|
/*
|
|
typedef struct {
|
|
SoupMessageHeaders *hdrs;
|
|
int index_common;
|
|
int index_uncommon;
|
|
} SoupMessageHeadersIterReal;
|
|
*/
|
|
iter := make([]byte, 12)
|
|
headersIterInit(&iter, hdrs)
|
|
|
|
var iterNext func(uintptr, *string, *string) int
|
|
purego.RegisterLibFunc(&iterNext, gtk, "soup_message_headers_iter_next")
|
|
|
|
var name string
|
|
var value string
|
|
h := http.Header{}
|
|
|
|
for iterNext(&iter, &name, &value) != 0 {
|
|
h.Add(name, value)
|
|
}
|
|
|
|
return h
|
|
}
|
|
|
|
func webkit_uri_scheme_request_finish(req uintptr, code int, header http.Header, stream uintptr, streamLength int64) error {
|
|
|
|
var newResponse func(uintptr, int64) string
|
|
purego.RegisterLibFunc(&newResponse, webkit, "webkit_uri_scheme_response_new")
|
|
var unRef func(uintptr)
|
|
purego.RegisterLibFunc(&unRef, gtk, "g_object_unref")
|
|
|
|
resp := newResponse(stream, streamLength)
|
|
defer unRef(resp)
|
|
|
|
var setStatus func(uintptr, int, string)
|
|
purego.RegisterLibFunc(&unRef, webkit, "webkit_uri_scheme_response_set_status")
|
|
|
|
setStatus(resp, code, cReason)
|
|
|
|
var setContentType func(uintptr, string)
|
|
purego.RegisterLibFunc(&unRef, webkit, "webkit_uri_scheme_response_set_content_type")
|
|
|
|
setContentType(resp, header.Get(HeaderContentType))
|
|
|
|
soup := gtk
|
|
var soupHeadersNew func(int) uintptr
|
|
purego.RegisterLibFunc(&unRef, soup, "soup_message_headers_new")
|
|
var soupHeadersAppend func(uintptr, string, string)
|
|
purego.RegisterLibFunc(&unRef, soup, "soup_message_headers_append")
|
|
|
|
hdrs := soupHeadersNew(SOUP_MESSAGE_HEADERS_RESPONSE)
|
|
for name, values := range header {
|
|
for _, value := range values {
|
|
soupHeadersAppend(hdrs, name, value)
|
|
}
|
|
}
|
|
|
|
var setHttpHeaders func(uintptr, uintptr)
|
|
purego.RegisterLibFunc(&unRef, webkit, "webkit_uri_scheme_response_set_http_headers")
|
|
|
|
setHttpHeaders(resp, hdrs)
|
|
var finishWithResponse func(uintptr, uintptr)
|
|
purego.RegisterLibFunc(&unRef, webkit, "webkit_uri_scheme_request_finish_with_response")
|
|
finishWithResponse(req, resp)
|
|
|
|
return nil
|
|
}
|
|
|
|
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...)
|
|
}
|