WASM reactive UI framework for Go: - reactive/ - Signal[T], Effect, Runtime - ui/ - Button, Text, Input, View, Canvas, SVG components - navigation/ - Router, guards, history management - auth/ - OIDC client for WASM applications - host/ - Static file server Extracted from arcadia as open-source component. Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
195
auth/http_wasm.go
Normal file
195
auth/http_wasm.go
Normal file
@@ -0,0 +1,195 @@
|
||||
//go:build js && wasm
|
||||
|
||||
package auth
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"syscall/js"
|
||||
)
|
||||
|
||||
// WASMHTTPClient handles HTTP requests in WASM environment
|
||||
type WASMHTTPClient struct{}
|
||||
|
||||
// HTTPResult represents the result of an HTTP request
|
||||
type HTTPResult struct {
|
||||
Data []byte
|
||||
Error error
|
||||
}
|
||||
|
||||
// HTTPCallback is called when HTTP request completes
|
||||
type HTTPCallback func(result HTTPResult)
|
||||
|
||||
// FetchJSON performs a GET request and unmarshals JSON response
|
||||
// This method blocks and should only be called from the main thread
|
||||
func (c *WASMHTTPClient) FetchJSON(url string, dest interface{}) error {
|
||||
result := make(chan HTTPResult, 1)
|
||||
|
||||
c.FetchJSONAsync(url, func(r HTTPResult) {
|
||||
result <- r
|
||||
})
|
||||
|
||||
r := <-result
|
||||
if r.Error != nil {
|
||||
return r.Error
|
||||
}
|
||||
|
||||
return json.Unmarshal(r.Data, dest)
|
||||
}
|
||||
|
||||
// FetchJSONAsync performs a GET request asynchronously using callback
|
||||
func (c *WASMHTTPClient) FetchJSONAsync(url string, callback HTTPCallback) {
|
||||
// Create fetch promise
|
||||
promise := js.Global().Call("fetch", url)
|
||||
|
||||
// Success handler
|
||||
var successFunc js.Func
|
||||
successFunc = js.FuncOf(func(this js.Value, args []js.Value) interface{} {
|
||||
response := args[0]
|
||||
if !response.Get("ok").Bool() {
|
||||
callback(HTTPResult{
|
||||
Error: fmt.Errorf("HTTP %d: %s", response.Get("status").Int(), response.Get("statusText").String()),
|
||||
})
|
||||
successFunc.Release()
|
||||
return nil
|
||||
}
|
||||
|
||||
// Get response text
|
||||
textPromise := response.Call("text")
|
||||
var textFunc js.Func
|
||||
textFunc = js.FuncOf(func(this js.Value, args []js.Value) interface{} {
|
||||
text := args[0].String()
|
||||
callback(HTTPResult{
|
||||
Data: []byte(text),
|
||||
})
|
||||
// Cleanup after callback completes
|
||||
textFunc.Release()
|
||||
successFunc.Release()
|
||||
return nil
|
||||
})
|
||||
|
||||
// Error handler for text promise
|
||||
var textErrorFunc js.Func
|
||||
textErrorFunc = js.FuncOf(func(this js.Value, args []js.Value) interface{} {
|
||||
callback(HTTPResult{
|
||||
Error: fmt.Errorf("failed to read response text: %v", args[0]),
|
||||
})
|
||||
// Cleanup
|
||||
textFunc.Release()
|
||||
textErrorFunc.Release()
|
||||
successFunc.Release()
|
||||
return nil
|
||||
})
|
||||
|
||||
textPromise.Call("then", textFunc).Call("catch", textErrorFunc)
|
||||
return nil
|
||||
})
|
||||
|
||||
// Error handler
|
||||
var errorFunc js.Func
|
||||
errorFunc = js.FuncOf(func(this js.Value, args []js.Value) interface{} {
|
||||
callback(HTTPResult{
|
||||
Error: fmt.Errorf("fetch error: %s", args[0].String()),
|
||||
})
|
||||
// Cleanup after callback completes
|
||||
errorFunc.Release()
|
||||
successFunc.Release()
|
||||
return nil
|
||||
})
|
||||
|
||||
promise.Call("then", successFunc).Call("catch", errorFunc)
|
||||
}
|
||||
|
||||
// PostForm performs a POST request with form data
|
||||
func (c *WASMHTTPClient) PostForm(url string, data url.Values, dest interface{}) error {
|
||||
result := make(chan HTTPResult, 1)
|
||||
|
||||
c.PostFormAsync(url, data, func(r HTTPResult) {
|
||||
result <- r
|
||||
})
|
||||
|
||||
r := <-result
|
||||
if r.Error != nil {
|
||||
return r.Error
|
||||
}
|
||||
|
||||
return json.Unmarshal(r.Data, dest)
|
||||
}
|
||||
|
||||
// PostFormAsync performs a POST request asynchronously using callback
|
||||
func (c *WASMHTTPClient) PostFormAsync(url string, data url.Values, callback HTTPCallback) {
|
||||
// Prepare fetch options
|
||||
headers := map[string]interface{}{
|
||||
"Content-Type": "application/x-www-form-urlencoded",
|
||||
}
|
||||
|
||||
options := map[string]interface{}{
|
||||
"method": "POST",
|
||||
"headers": headers,
|
||||
"body": data.Encode(),
|
||||
}
|
||||
|
||||
// Convert options to JS object
|
||||
jsOptions := js.ValueOf(options)
|
||||
|
||||
// Make the request
|
||||
promise := js.Global().Call("fetch", url, jsOptions)
|
||||
|
||||
// Success handler
|
||||
var successFunc js.Func
|
||||
successFunc = js.FuncOf(func(this js.Value, args []js.Value) interface{} {
|
||||
response := args[0]
|
||||
if !response.Get("ok").Bool() {
|
||||
callback(HTTPResult{
|
||||
Error: fmt.Errorf("HTTP %d: %s", response.Get("status").Int(), response.Get("statusText").String()),
|
||||
})
|
||||
successFunc.Release()
|
||||
return nil
|
||||
}
|
||||
|
||||
// Get response text
|
||||
textPromise := response.Call("text")
|
||||
var textFunc js.Func
|
||||
textFunc = js.FuncOf(func(this js.Value, args []js.Value) interface{} {
|
||||
text := args[0].String()
|
||||
callback(HTTPResult{
|
||||
Data: []byte(text),
|
||||
})
|
||||
// Cleanup after callback completes
|
||||
textFunc.Release()
|
||||
successFunc.Release()
|
||||
return nil
|
||||
})
|
||||
|
||||
// Error handler for text promise
|
||||
var textErrorFunc js.Func
|
||||
textErrorFunc = js.FuncOf(func(this js.Value, args []js.Value) interface{} {
|
||||
callback(HTTPResult{
|
||||
Error: fmt.Errorf("failed to read response text: %v", args[0]),
|
||||
})
|
||||
// Cleanup
|
||||
textFunc.Release()
|
||||
textErrorFunc.Release()
|
||||
successFunc.Release()
|
||||
return nil
|
||||
})
|
||||
|
||||
textPromise.Call("then", textFunc).Call("catch", textErrorFunc)
|
||||
return nil
|
||||
})
|
||||
|
||||
// Error handler
|
||||
var errorFunc js.Func
|
||||
errorFunc = js.FuncOf(func(this js.Value, args []js.Value) interface{} {
|
||||
callback(HTTPResult{
|
||||
Error: fmt.Errorf("fetch error: %s", args[0].String()),
|
||||
})
|
||||
// Cleanup after callback completes
|
||||
errorFunc.Release()
|
||||
successFunc.Release()
|
||||
return nil
|
||||
})
|
||||
|
||||
promise.Call("then", successFunc).Call("catch", errorFunc)
|
||||
}
|
||||
Reference in New Issue
Block a user