mirror of
https://github.com/nlepage/go-wasm-http-server.git
synced 2026-01-12 01:59:14 +00:00
🚧
This commit is contained in:
3
internal/whutil/package.go
Normal file
3
internal/whutil/package.go
Normal file
@@ -0,0 +1,3 @@
|
||||
// Package whutil stands for WASM HTTP utilities.
|
||||
// It contains internal utilities for github.com/nlepage/go-wasm-http-server.
|
||||
package whutil
|
||||
55
internal/whutil/promise.go
Normal file
55
internal/whutil/promise.go
Normal file
@@ -0,0 +1,55 @@
|
||||
package whutil
|
||||
|
||||
import (
|
||||
"syscall/js"
|
||||
)
|
||||
|
||||
// Promise is JS Promise
|
||||
type Promise js.Value
|
||||
|
||||
// NewPromise creates a new JS Promise
|
||||
func NewPromise(cb func(resolve, reject func(interface{}))) Promise {
|
||||
var cbFunc js.Func
|
||||
|
||||
cbFunc = js.FuncOf(func(_ js.Value, args []js.Value) interface{} {
|
||||
defer cbFunc.Release()
|
||||
|
||||
cb(
|
||||
func(v interface{}) {
|
||||
args[0].Invoke(v)
|
||||
},
|
||||
func(v interface{}) {
|
||||
args[1].Invoke(v)
|
||||
},
|
||||
)
|
||||
|
||||
return js.Undefined()
|
||||
})
|
||||
|
||||
return Promise(js.Global().Get("Promise").New(cbFunc))
|
||||
}
|
||||
|
||||
// Await waits for the Promise to be resolved and returns the value
|
||||
func (p Promise) Await() js.Value {
|
||||
ch := make(chan js.Value)
|
||||
p.Then(func(v js.Value) {
|
||||
ch <- v
|
||||
})
|
||||
return <-ch
|
||||
}
|
||||
|
||||
// Then calls cb with the value when the Promise is resolved
|
||||
func (p Promise) Then(cb func(js.Value)) {
|
||||
var then js.Func
|
||||
then = js.FuncOf(func(_ js.Value, args []js.Value) interface{} {
|
||||
defer then.Release()
|
||||
cb(args[0])
|
||||
return nil
|
||||
})
|
||||
js.Value(p).Call("then", then)
|
||||
}
|
||||
|
||||
// Value returns the Promise as a js.Value
|
||||
func (p Promise) Value() js.Value {
|
||||
return js.Value(p)
|
||||
}
|
||||
39
internal/whutil/request.go
Normal file
39
internal/whutil/request.go
Normal file
@@ -0,0 +1,39 @@
|
||||
package whutil
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"net/http"
|
||||
"syscall/js"
|
||||
)
|
||||
|
||||
// Request is a JS Request
|
||||
type Request js.Value
|
||||
|
||||
// HTTPRequest builds and returns this equivalent http.Request
|
||||
func (r *Request) HTTPRequest() (*http.Request, error) {
|
||||
rValue := js.Value(*r)
|
||||
|
||||
jsBody := js.Global().Get("Uint8Array").New(Promise(rValue.Call("arrayBuffer")).Await())
|
||||
body := make([]byte, jsBody.Get("length").Int())
|
||||
js.CopyBytesToGo(body, jsBody)
|
||||
|
||||
req, err := http.NewRequest(
|
||||
rValue.Get("method").String(),
|
||||
rValue.Get("url").String(),
|
||||
bytes.NewBuffer(body),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
headersIt := rValue.Get("headers").Call("entries")
|
||||
for {
|
||||
v := headersIt.Call("next")
|
||||
if v.Get("done").Bool() {
|
||||
break
|
||||
}
|
||||
req.Header.Set(v.Index(0).String(), v.Index(1).String())
|
||||
}
|
||||
|
||||
return req, nil
|
||||
}
|
||||
58
internal/whutil/response_writer.go
Normal file
58
internal/whutil/response_writer.go
Normal file
@@ -0,0 +1,58 @@
|
||||
package whutil
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"net/http"
|
||||
"syscall/js"
|
||||
)
|
||||
|
||||
// ResponseWriter implements http.ResponseWriter
|
||||
type ResponseWriter struct {
|
||||
header http.Header
|
||||
buf *bytes.Buffer
|
||||
statusCode int
|
||||
}
|
||||
|
||||
// NewResponseWriter creates a new ResponseWriter
|
||||
func NewResponseWriter() *ResponseWriter {
|
||||
return &ResponseWriter{
|
||||
header: http.Header{},
|
||||
buf: bytes.NewBuffer(nil),
|
||||
statusCode: 0,
|
||||
}
|
||||
}
|
||||
|
||||
var _ http.ResponseWriter = (*ResponseWriter)(nil)
|
||||
|
||||
// Header implements http.ResponseWriter.Header
|
||||
func (rw *ResponseWriter) Header() http.Header {
|
||||
return rw.header
|
||||
}
|
||||
|
||||
// Write implements http.ResponseWriter.Write
|
||||
func (rw *ResponseWriter) Write(p []byte) (int, error) {
|
||||
return rw.buf.Write(p)
|
||||
}
|
||||
|
||||
// WriteHeader implements http.ResponseWriter.WriteHeader
|
||||
func (rw *ResponseWriter) WriteHeader(statusCode int) {
|
||||
rw.statusCode = statusCode
|
||||
}
|
||||
|
||||
// JSResponse builds and returns the equivalent JS Response
|
||||
func (rw *ResponseWriter) JSResponse() js.Value {
|
||||
init := js.Global().Get("Object").New()
|
||||
|
||||
if rw.statusCode != 0 {
|
||||
init.Set("status", rw.statusCode)
|
||||
}
|
||||
|
||||
if len(rw.header) != 0 {
|
||||
init.Set("headers", map[string][]string(rw.header))
|
||||
}
|
||||
|
||||
jsBody := js.Global().Get("Uint8Array").New(rw.buf.Len())
|
||||
js.CopyBytesToJS(jsBody, rw.buf.Bytes())
|
||||
|
||||
return js.Global().Get("Response").New(jsBody, init)
|
||||
}
|
||||
Reference in New Issue
Block a user