diff --git a/docs/api.go b/docs/api.go index 887e569..45d7ac6 100644 --- a/docs/api.go +++ b/docs/api.go @@ -1,7 +1,6 @@ package main import ( - "context" "encoding/json" "fmt" "net/http" @@ -10,7 +9,7 @@ import ( ) func main() { - defer fmt.Println("api stopping...") + defer fmt.Println("api stopped...") http.HandleFunc("/hello", func(res http.ResponseWriter, req *http.Request) { params := make(map[string]string) @@ -25,8 +24,5 @@ func main() { } }) - var release = wasmhttp.Serve(nil) - defer release() - - <-context.Background().Done() + wasmhttp.Serve(nil) } diff --git a/docs/api.wasm b/docs/api.wasm index 46b3538..3f4b9e8 100755 Binary files a/docs/api.wasm and b/docs/api.wasm differ diff --git a/docs/sw.js b/docs/sw.js index c0f4e19..e5c8310 100644 --- a/docs/sw.js +++ b/docs/sw.js @@ -8,4 +8,4 @@ addEventListener('activate', event => { event.waitUntil(clients.claim()) }) -registerWasmHTTPListener('api.wasm', 'api') +registerWasmHTTPListener('api.wasm', { base: 'api' }) diff --git a/serve.go b/serve.go index 031d493..d025c95 100644 --- a/serve.go +++ b/serve.go @@ -1,6 +1,7 @@ package wasmhttp import ( + "context" "fmt" "net/http" "strings" @@ -10,7 +11,7 @@ import ( ) // Serve serves HTTP requests using handler or http.DefaultServeMux if handler is nil. -func Serve(handler http.Handler) func() { +func Serve(handler http.Handler) { var h = handler if h == nil { h = http.DefaultServeMux @@ -57,8 +58,27 @@ func Serve(handler http.Handler) func() { return resPromise }) + defer cb.Release() js.Global().Get("wasmhttp").Call("setHandler", cb) - return cb.Release + <-Context().Done() +} + +func Context() context.Context { + var timeoutPromise = js.Global().Get("wasmhttp").Get("timeoutPromise") + + if timeoutPromise.IsUndefined() { + return context.Background() + } + + var ctx, cancel = context.WithCancel(context.Background()) + + go func() { + whutil.Promise{timeoutPromise}.Await() + + cancel() + }() + + return ctx } diff --git a/sw.js b/sw.js index d402116..8a23c30 100644 --- a/sw.js +++ b/sw.js @@ -1,13 +1,27 @@ importScripts('https://cdn.jsdelivr.net/gh/golang/go@go1.15.7/misc/wasm/wasm_exec.js') -function registerWasmHTTPListener(wasm, base, args = []) { +function registerWasmHTTPListener(wasm, { base, args = [], timeout = 25 } = {}) { let path = new URL(registration.scope).pathname if (base && base !== '') path = `${trimEnd(path, '/')}/${trimStart(base, '/')}` + let timeoutPromise + let resetTimeout + if (timeout) { + let resolveTimeout + timeoutPromise = new Promise(resolve => { resolveTimeout = resolve }) + let timeoutId + resetTimeout = () => { + clearTimeout(timeoutId) + timeoutId = setTimeout(resolveTimeout, timeout * 1000) + } + resetTimeout() + } + const handlerPromise = new Promise(setHandler => { self.wasmhttp = { path, setHandler, + timeoutPromise, } }) @@ -16,6 +30,8 @@ function registerWasmHTTPListener(wasm, base, args = []) { WebAssembly.instantiateStreaming(fetch(wasm), go.importObject).then(({ instance }) => go.run(instance)) addEventListener('fetch', e => { + resetTimeout?.() + const { pathname } = new URL(e.request.url) if (!pathname.startsWith(path)) return