diff --git a/LICENSE b/LICENSE
index ff42636..a90a021 100644
--- a/LICENSE
+++ b/LICENSE
@@ -186,7 +186,7 @@
same "printed page" as the copyright notice for easier
identification within third-party archives.
- Copyright 2019 Nicolas Lepage
+ Copyright 2021 Nicolas Lepage
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
diff --git a/docs/api.go b/docs/api.go
index def96b7..ebdf1e9 100644
--- a/docs/api.go
+++ b/docs/api.go
@@ -4,39 +4,23 @@ import (
"encoding/json"
"fmt"
"net/http"
- "time"
wasmhttp "github.com/nlepage/go-wasm-http-server"
)
-var no = 1
-
func main() {
http.HandleFunc("/hello", func(res http.ResponseWriter, req *http.Request) {
- h, m, s := time.Now().Clock()
- fmt.Printf("hello at %02d:%02d:%02d\n", h, m, s)
-
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! (%d)", params["name"], no),
+ "message": fmt.Sprintf("Hello %s!", params["name"]),
}); err != nil {
panic(err)
}
- no++
})
- wasmhttp.Serve(nil)
-
- go func() {
- for range time.Tick(time.Second) {
- h, m, s := time.Now().Clock()
- fmt.Printf("tick at %02d:%02d:%02d\n", h, m, s)
- }
- }()
-
- select {}
+ wasmhttp.ServeOnce(nil)
}
diff --git a/docs/api.wasm b/docs/api.wasm
index 34918f3..bde8613 100755
Binary files a/docs/api.wasm and b/docs/api.wasm differ
diff --git a/docs/index.html b/docs/index.html
index f01df0e..cf9b3ea 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -2,8 +2,9 @@
go-wasm-http-server demo
-
\ No newline at end of file
diff --git a/docs/sw.js b/docs/sw.js
index 1c1fe78..7d6493f 100644
--- a/docs/sw.js
+++ b/docs/sw.js
@@ -1 +1,3 @@
importScripts('https://cdn.jsdelivr.net/gh/nlepage/go-wasm-http-server@latest/sw.js')
+
+registerWasmHTTPListener('api.wasm')
diff --git a/serve.go b/serve.go
index c424565..0b62083 100644
--- a/serve.go
+++ b/serve.go
@@ -1,6 +1,7 @@
package wasmhttp
import (
+ "context"
"fmt"
"net/http"
"os"
@@ -12,35 +13,34 @@ import (
// Serve serves HTTP requests using handler or http.DefaultServeMux if handler is nil.
func Serve(handler http.Handler) func() {
- h := handler
+ var h = handler
if h == nil {
h = http.DefaultServeMux
}
- path := os.Getenv("WASMHTTP_PATH")
+ var path = os.Getenv("WASMHTTP_PATH")
if !strings.HasSuffix(path, "/") {
path = path + "/"
}
if path != "" { // FIXME always true since / suffix is added to path
- prefix := os.Getenv("WASMHTTP_PATH")
+ var prefix = os.Getenv("WASMHTTP_PATH")
for strings.HasSuffix(prefix, "/") {
prefix = strings.TrimSuffix(prefix, "/")
}
- mux := http.NewServeMux()
+ var 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]}
+ var cb = js.FuncOf(func(_ js.Value, args []js.Value) interface{} {
+ var jsReq = whutil.Request{args[0]}
var resPromise = whutil.NewPromise(func(resolve whutil.PromiseResolve, reject whutil.PromiseReject) {
go func() {
defer func() {
- r := recover()
- if r != nil {
+ if r := recover(); r != nil {
if err, ok := r.(error); ok {
reject(fmt.Sprintf("wasmhttp: panic: %+v\n", err))
} else {
@@ -49,12 +49,12 @@ func Serve(handler http.Handler) func() {
}
}()
- req, err := jsReq.HTTPRequest()
+ var req, err = jsReq.HTTPRequest()
if err != nil {
panic(err)
}
- res := whutil.NewResponseWriter()
+ var res = whutil.NewResponseWriter()
h.ServeHTTP(res, req)
@@ -69,3 +69,65 @@ func Serve(handler http.Handler) func() {
return cb.Release
}
+
+func ServeOnce(handler http.Handler) {
+ var ctx, cancel = context.WithCancel(context.Background())
+
+ var h = handler
+ if h == nil {
+ h = http.DefaultServeMux
+ }
+
+ var path = os.Getenv("WASMHTTP_PATH")
+ if !strings.HasSuffix(path, "/") {
+ path = path + "/"
+ }
+
+ if path != "" { // FIXME always true since / suffix is added to path
+ var prefix = os.Getenv("WASMHTTP_PATH")
+ for strings.HasSuffix(prefix, "/") {
+ prefix = strings.TrimSuffix(prefix, "/")
+ }
+
+ var mux = http.NewServeMux()
+ mux.Handle(path, http.StripPrefix(prefix, h))
+ h = mux
+ }
+
+ var cb = js.FuncOf(func(_ js.Value, args []js.Value) interface{} {
+ var jsReq = whutil.Request{args[0]}
+
+ var resPromise = whutil.NewPromise(func(resolve whutil.PromiseResolve, reject whutil.PromiseReject) {
+ go func() {
+ defer cancel()
+
+ defer func() {
+ if r := recover(); r != nil {
+ if err, ok := r.(error); ok {
+ reject(fmt.Sprintf("wasmhttp: panic: %+v\n", err))
+ } else {
+ reject(fmt.Sprintf("wasmhttp: panic: %v\n", r))
+ }
+ }
+ }()
+
+ var req, err = jsReq.HTTPRequest()
+ if err != nil {
+ panic(err)
+ }
+
+ var res = whutil.NewResponseWriter()
+
+ h.ServeHTTP(res, req)
+
+ resolve(res)
+ }()
+ })
+
+ return resPromise
+ })
+
+ js.Global().Get("wasmhttp").Call("registerHandler", os.Getenv("WASMHTTP_HANDLER_ID"), cb)
+
+ <-ctx.Done()
+}
diff --git a/sw.js b/sw.js
index a4638d2..f6b1645 100644
--- a/sw.js
+++ b/sw.js
@@ -76,3 +76,23 @@ addEventListener('fetch', e => {
e.respondWith(handler(e.request))
})
+
+function registerWasmHTTPListener(wasm, base, args) {
+ let path = new URL(registration.scope).pathname
+ if (base && base !== '') path = `${trimEnd(path, '/')}/${trimStart(base, '/')}`
+
+ addEventListener('fetch', async e => {
+ const { pathname } = new URL(e.request.url)
+ if (!pathname.startsWith(path)) return
+
+ const handlerId = `${nextHandlerId++}`
+ const handlerPromise = new Promise(resolve => handlerResolvers[handlerId] = resolve)
+
+ // FIXME await ? catch ?
+ startWasm(wasm, { env: { WASMHTTP_HANDLER_ID: handlerId, WASMHTTP_PATH: path }, args })
+
+ const handler = await handlerPromise
+
+ e.respondWith(handler(e.request))
+ })
+}
\ No newline at end of file