This commit is contained in:
Nicolas Lepage 2021-01-21 23:07:42 +01:00
parent 3b1987e60b
commit 51d77eecb2
No known key found for this signature in database
GPG Key ID: B0879E35E66D8F6F
7 changed files with 99 additions and 33 deletions

View File

@ -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.

View File

@ -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(&params); 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)
}

Binary file not shown.

View File

@ -2,8 +2,9 @@
<html>
<head>
<title>go-wasm-http-server demo</title>
<script src="https://cdn.jsdelivr.net/gh/nlepage/go-wasm-http-server@latest/index.js"></script>
<script>
navigator.serviceWorker.register('sw.js')
async function hello() {
res = await fetch('api/hello', {
method: 'POST',
@ -20,8 +21,5 @@
<body>
<label for="name">Name : </label><input id="name" value="World">
<button onclick="hello()">Hello</button>
<script>
wasmhttp.register('api.wasm', { base: 'api' })
</script>
</body>
</html>

View File

@ -1 +1,3 @@
importScripts('https://cdn.jsdelivr.net/gh/nlepage/go-wasm-http-server@latest/sw.js')
registerWasmHTTPListener('api.wasm')

View File

@ -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()
}

20
sw.js
View File

@ -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))
})
}