diff --git a/docs/index.html b/docs/index.html new file mode 100644 index 0000000..602f8ef --- /dev/null +++ b/docs/index.html @@ -0,0 +1,9 @@ + + + + + + + \ No newline at end of file diff --git a/docs/sw.js b/docs/sw.js new file mode 100644 index 0000000..910ce79 --- /dev/null +++ b/docs/sw.js @@ -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', +}) diff --git a/docs/test.go b/docs/test.go new file mode 100644 index 0000000..0c0ae18 --- /dev/null +++ b/docs/test.go @@ -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(¶ms); 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 {} +} diff --git a/docs/test.wasm b/docs/test.wasm new file mode 100755 index 0000000..b0e452c Binary files /dev/null and b/docs/test.wasm differ diff --git a/index.js b/index.js index b01628b..991986f 100644 --- a/index.js +++ b/index.js @@ -1,31 +1,50 @@ let nextHandlerId = 1 const handlerResolvers = {} -const startWasm = async (wasm, WASMHTTP_HANDLER_ID, WASMHTTP_BASE) => { +const startWasm = async (wasm, WASMHTTP_HANDLER_ID, WASMHTTP_PATH) => { const go = new Go() go.env = { WASMHTTP_HANDLER_ID, - WASMHTTP_BASE, + WASMHTTP_PATH, } const { instance } = await WebAssembly.instantiateStreaming(fetch(wasm), go.importObject) 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 = { - serve: async ({ wasm, base } = { - base: '', - }) => { + serve: async ({ wasm, base } = {}) => { try { - if (!wasm) throw TypeError('option.wasm must be defined') + if (!wasm) throw TypeError('options.wasm must be defined') const handlerId = `${nextHandlerId++}` 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) { console.error('wasmhttp: error:', e) + throw e } }, diff --git a/internal/whutil/response_writer.go b/internal/whutil/response_writer.go index e9877e4..36ba5ac 100644 --- a/internal/whutil/response_writer.go +++ b/internal/whutil/response_writer.go @@ -48,7 +48,11 @@ func (rw *ResponseWriter) JSResponse() js.Value { } 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()) diff --git a/serve.go b/serve.go index b967dd8..f768b51 100644 --- a/serve.go +++ b/serve.go @@ -4,6 +4,7 @@ import ( "fmt" "net/http" "os" + "strings" "syscall/js" "github.com/nlepage/go-wasm-http-server/internal/whutil" @@ -16,6 +17,22 @@ func Serve(handler http.Handler) func() { 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{} { jsReq := whutil.Request(args[0]) @@ -29,14 +46,14 @@ func Serve(handler http.Handler) func() { r := recover() if r != nil { if err, ok := r.(error); ok { - fmt.Fprintf("wasmhttp: panic: %+v", err) + fmt.Printf("wasmhttp: panic: %+v\n", err) } else { - fmt.Fprintf("wasmhttp: panic: %v", r) + fmt.Printf("wasmhttp: panic: %v\n", r) } res := whutil.NewResponseWriter() res.WriteHeader(500) - resolveRes(res) + resolveRes(res.JSResponse()) } }() @@ -47,7 +64,7 @@ func Serve(handler http.Handler) func() { res := whutil.NewResponseWriter() - handler.ServeHTTP(res, req) + h.ServeHTTP(res, req) resolveRes(res.JSResponse()) }()