Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Commit 3c5472e

Browse files
committed
Add self-sufficient e2e WASM example template
A sample WASM application featuring Transport WASM bridge will soon follow. Thinking of doing an X509 public certificate verification as an example code, as it's a good showcase of encoding/decoding of base64 and pem container format as well as cryptographic operations.
1 parent 0e5ed52 commit 3c5472e

File tree

7 files changed

+818
-1
lines changed

7 files changed

+818
-1
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
package example
1+
package sample_wasm_app
22

33
//go:generate bash -c "GOARCH=wasm; GOOS=js; go build -o ${OUT_DIR}/main.wasm main.go"

wasm/example/main.go wasm/example/sample_wasm_app/main.go

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
//go:build js && wasm
2+
// +build js,wasm
23

34
// Copyright 2021 VMware, Inc.
45
// SPDX-License-Identifier: BSD-2-Clause

wasm/example/server/main.go

+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package main
2+
3+
import (
4+
"context"
5+
"errors"
6+
"github.com/vmware/transport-go/wasm/example/server/render"
7+
"io/fs"
8+
"log"
9+
"net/http"
10+
"os"
11+
"os/signal"
12+
"path"
13+
"strings"
14+
"syscall"
15+
)
16+
17+
func main() {
18+
sigChan := make(chan os.Signal)
19+
signal.Notify(sigChan, syscall.SIGINT, syscall.SIGKILL)
20+
server := exampleServer()
21+
22+
go func() {
23+
<-sigChan
24+
server.Shutdown(context.Background())
25+
}()
26+
27+
log.Println("example server running at http://localhost:30080")
28+
_ = server.ListenAndServe()
29+
}
30+
31+
func exampleServer() *http.Server {
32+
handler := http.NewServeMux()
33+
handler.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
34+
// template
35+
tmpl := render.GetTemplate(render.IndexRoute)
36+
err := tmpl.Execute(w, nil)
37+
if err != nil {
38+
http.Error(w, err.Error(), 500)
39+
}
40+
})
41+
42+
handler.HandleFunc("/assets/", func(w http.ResponseWriter, r *http.Request) {
43+
split := strings.Split(r.RequestURI[1:], "/")
44+
resourcePath := path.Join("templates", strings.Join(split[1:], "/"))
45+
b, err := fs.ReadFile(render.FS, resourcePath)
46+
if err != nil {
47+
if errors.Is(err, fs.ErrNotExist) {
48+
http.NotFound(w, r)
49+
} else {
50+
http.Error(w, err.Error(), http.StatusInternalServerError)
51+
}
52+
return
53+
}
54+
55+
w.Write(b)
56+
})
57+
58+
s := &http.Server{
59+
Addr: ":30080",
60+
Handler: handler,
61+
}
62+
63+
return s
64+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package render
2+
3+
import (
4+
"embed"
5+
"fmt"
6+
"html/template"
7+
"io"
8+
"log"
9+
)
10+
11+
type ExampleRoute int
12+
13+
const (
14+
IndexRoute ExampleRoute = iota
15+
)
16+
17+
//go:embed templates/*
18+
var FS embed.FS
19+
20+
type Tmpl struct {
21+
tmpl *template.Template
22+
funcs template.FuncMap
23+
}
24+
25+
func (t *Tmpl) SetFuncs(funcs template.FuncMap) {
26+
t.funcs = funcs
27+
}
28+
29+
func (t *Tmpl) Execute(w io.Writer, data interface{}) error {
30+
return t.tmpl.Funcs(t.funcs).Execute(w, data)
31+
}
32+
33+
func GetTemplate(route ExampleRoute) *Tmpl {
34+
var tmpl *Tmpl
35+
switch route {
36+
case IndexRoute:
37+
tmpl = newTemplate("templates/index.html", "templates/common.html")
38+
default:
39+
tmpl = newTemplate("")
40+
}
41+
return tmpl
42+
}
43+
44+
func newTemplate(embedded ...string) *Tmpl {
45+
var parsed *template.Template
46+
var err error
47+
48+
if len(embedded) > 0 {
49+
parsed, err = template.ParseFS(FS, embedded...)
50+
if err != nil {
51+
log.Printf("warning: some child templates could not be parsed: %v", fmt.Errorf("failed to parse child templates: %w", err))
52+
}
53+
}
54+
55+
return &Tmpl{tmpl: parsed}
56+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
{{- define "transport_typescript_lib" }}
2+
<script src="https://cdn.jsdelivr.net/npm/[email protected]/bundles/rxjs.umd.min.js"></script>
3+
<script src="https://cdn.jsdelivr.net/npm/@vmw/transport@latest/transport.umd.min.js"></script>
4+
<script>
5+
transport.TransportEventBus.bootWithOptions(1, false, true);
6+
</script>
7+
{{- end }}
8+
9+
{{- define "go_wasm_exec_script" }}
10+
<script src="/assets/wasm_exec.js"></script>
11+
<script>
12+
if (!WebAssembly.instantiateStreaming) { // polyfill
13+
WebAssembly.instantiateStreaming = async (resp, importObject) => {
14+
const source = await (await resp).arrayBuffer();
15+
return await WebAssembly.instantiate(source, importObject);
16+
};
17+
}
18+
19+
const go = new Go();
20+
let mod, inst;
21+
WebAssembly.instantiateStreaming(fetch("{{ . }}"), go.importObject).then((result) => {
22+
mod = result.module;
23+
inst = result.instance;
24+
AppEventBus.sendResponseMessage('wasm_loaded_chan', true);
25+
}).catch((err) => {
26+
console.error(err);
27+
});
28+
29+
async function run() {
30+
await go.run(inst);
31+
inst = await WebAssembly.instantiate(mod, go.importObject); // reset instance
32+
}
33+
</script>
34+
{{- end }}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8">
5+
<title>Rxjs</title>
6+
<base href="/">
7+
<meta name="viewport" content="width=device-width, initial-scale=1">
8+
<link rel="icon" type="image/x-icon" href="favicon.ico">
9+
{{- template "transport_typescript_lib" -}}
10+
{{- template "go_wasm_exec_script" "/assets/main.wasm" -}}
11+
</head>
12+
<body>
13+
<h1>WASM Playground</h1>
14+
<script>
15+
// set up a channel that wasm_exec will send a signal to once our WASM application is loaded
16+
// and ready to be executed. note that if you try to run(), it will fail because the file will most likely
17+
// has not yet loaded. see templates/common.html as well to see how and when the message is sent down the channel.
18+
const wasmLoadedHandler = AppEventBus.listenOnce('wasm_loaded_chan');
19+
wasmLoadedHandler.handle(async () => {
20+
console.log('wasm bundle downloaded and loaded. executing');
21+
await run();
22+
});
23+
24+
</script>
25+
</body>
26+
</html>

0 commit comments

Comments
 (0)