This commit is contained in:
Nicolas Lepage 2019-11-27 11:20:52 +01:00
parent 5a9f7c57a2
commit bffb45066d
No known key found for this signature in database
GPG Key ID: B0879E35E66D8F6F
7 changed files with 99 additions and 13 deletions

9
docs/index.html Normal file
View File

@ -0,0 +1,9 @@
<!DOCTYPE html>
<html>
<head></head>
<body>
<script>
navigator.serviceWorker.register('sw.js')
</script>
</body>
</html>

9
docs/sw.js Normal file
View File

@ -0,0 +1,9 @@
importScripts(
'https://raw.githubusercontent.com/nlepage/go-wasm-http-server/master/lib/wasm_exec/wasm_exec.js',
'https://raw.githubusercontent.com/nlepage/go-wasm-http-server/master/index.js',
)
wasmhttp.serve({
wasm: 'test.wasm',
base: '/test',
})

28
docs/test.go Normal file
View File

@ -0,0 +1,28 @@
package main
import (
"encoding/json"
"fmt"
"net/http"
wasmhttp "github.com/nlepage/go-wasm-http-server"
)
func main() {
http.HandleFunc("/hello", func(res http.ResponseWriter, req *http.Request) {
params := make(map[string]string)
if err := json.NewDecoder(req.Body).Decode(&params); err != nil {
panic(err)
}
if err := json.NewEncoder(res).Encode(map[string]string{
"message": fmt.Sprintf("Hello %s!", params["name"]),
}); err != nil {
panic(err)
}
})
wasmhttp.Serve(nil)
select {}
}

BIN
docs/test.wasm Executable file

Binary file not shown.

View File

@ -1,31 +1,50 @@
let nextHandlerId = 1 let nextHandlerId = 1
const handlerResolvers = {} const handlerResolvers = {}
const startWasm = async (wasm, WASMHTTP_HANDLER_ID, WASMHTTP_BASE) => { const startWasm = async (wasm, WASMHTTP_HANDLER_ID, WASMHTTP_PATH) => {
const go = new Go() const go = new Go()
go.env = { go.env = {
WASMHTTP_HANDLER_ID, WASMHTTP_HANDLER_ID,
WASMHTTP_BASE, WASMHTTP_PATH,
} }
const { instance } = await WebAssembly.instantiateStreaming(fetch(wasm), go.importObject) const { instance } = await WebAssembly.instantiateStreaming(fetch(wasm), go.importObject)
return go.run(instance) return go.run(instance)
} }
const trimStart = (s, c) => {
let r = s
while (r.startsWith(c)) r = r.slice(c.length)
return r
}
const trimEnd = (s, c) => {
let r = s
while (r.endsWith(c)) r = r.slice(0, -c.length)
return r
}
self.wasmhttp = { self.wasmhttp = {
serve: async ({ wasm, base } = { serve: async ({ wasm, base } = {}) => {
base: '',
}) => {
try { try {
if (!wasm) throw TypeError('option.wasm must be defined') if (!wasm) throw TypeError('options.wasm must be defined')
const handlerId = `${nextHandlerId++}` const handlerId = `${nextHandlerId++}`
const handler = new Promise(resolve => handlerResolvers[handlerId] = resolve) const handler = new Promise(resolve => handlerResolvers[handlerId] = resolve)
startWasm(wasm, handlerId, base) let path = new URL(registration.scope).pathname
if (base && base !== '') path = `${trimEnd(path, '/')}/${trimStart(base, '/')}`
addEventListener('fetch', async e => e.respondWith((await handler)(e.request))) startWasm(wasm, handlerId, path)
addEventListener('fetch', async e => {
if (!new URL(e.request.url).pathname.startsWith(path)) return
// FIXME try catch
e.respondWith((await handler)(e.request))
})
} catch (e) { } catch (e) {
console.error('wasmhttp: error:', e) console.error('wasmhttp: error:', e)
throw e
} }
}, },

View File

@ -48,7 +48,11 @@ func (rw *ResponseWriter) JSResponse() js.Value {
} }
if len(rw.header) != 0 { if len(rw.header) != 0 {
init.Set("headers", map[string][]string(rw.header)) headers := make(map[string]interface{}, len(rw.header))
for k := range rw.header {
headers[k] = rw.header.Get(k)
}
init.Set("headers", headers)
} }
jsBody := js.Global().Get("Uint8Array").New(rw.buf.Len()) jsBody := js.Global().Get("Uint8Array").New(rw.buf.Len())

View File

@ -4,6 +4,7 @@ import (
"fmt" "fmt"
"net/http" "net/http"
"os" "os"
"strings"
"syscall/js" "syscall/js"
"github.com/nlepage/go-wasm-http-server/internal/whutil" "github.com/nlepage/go-wasm-http-server/internal/whutil"
@ -16,6 +17,22 @@ func Serve(handler http.Handler) func() {
h = http.DefaultServeMux h = http.DefaultServeMux
} }
path := os.Getenv("WASMHTTP_PATH")
if !strings.HasSuffix(path, "/") {
path = path + "/"
}
if path != "" {
prefix := os.Getenv("WASMHTTP_PATH")
for strings.HasSuffix(prefix, "/") {
prefix = strings.TrimSuffix(prefix, "/")
}
mux := http.NewServeMux()
mux.Handle(path, http.StripPrefix(prefix, h))
h = mux
}
cb := js.FuncOf(func(_ js.Value, args []js.Value) interface{} { cb := js.FuncOf(func(_ js.Value, args []js.Value) interface{} {
jsReq := whutil.Request(args[0]) jsReq := whutil.Request(args[0])
@ -29,14 +46,14 @@ func Serve(handler http.Handler) func() {
r := recover() r := recover()
if r != nil { if r != nil {
if err, ok := r.(error); ok { if err, ok := r.(error); ok {
fmt.Fprintf("wasmhttp: panic: %+v", err) fmt.Printf("wasmhttp: panic: %+v\n", err)
} else { } else {
fmt.Fprintf("wasmhttp: panic: %v", r) fmt.Printf("wasmhttp: panic: %v\n", r)
} }
res := whutil.NewResponseWriter() res := whutil.NewResponseWriter()
res.WriteHeader(500) res.WriteHeader(500)
resolveRes(res) resolveRes(res.JSResponse())
} }
}() }()
@ -47,7 +64,7 @@ func Serve(handler http.Handler) func() {
res := whutil.NewResponseWriter() res := whutil.NewResponseWriter()
handler.ServeHTTP(res, req) h.ServeHTTP(res, req)
resolveRes(res.JSResponse()) resolveRes(res.JSResponse())
}() }()