-
Notifications
You must be signed in to change notification settings - Fork 39
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* add go stub * add serve methods to go kit * add go-basic example * add go kv example * add go params example * add go envs example * use sjson and add Go docs
- Loading branch information
Showing
21 changed files
with
785 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,331 @@ | ||
--- | ||
sidebar_position: 5 | ||
--- | ||
|
||
# Go | ||
|
||
Go workers are compiled into a WASI module using [TinyGo](https://tinygo.org/docs/guides/webassembly/). Then, they are loaded by Wasm Workers Server and start processing requests. | ||
|
||
## Your first Go worker | ||
|
||
Workers can be implemented either as an [http.Handler](https://pkg.go.dev/net/http#Handler) or an [http.HandlerFunc](https://pkg.go.dev/net/http#HandlerFunc). | ||
|
||
In this example, the worker will get a request and print all the related information. | ||
|
||
1. Create a new Go mod project | ||
|
||
``` | ||
go mod init workers-in-go | ||
``` | ||
1. Add the Wasm Workers Server Go dependency | ||
``` | ||
go get -u github.com/vmware-labs/wasm-workers-server/kits/go/worker | ||
``` | ||
1. Create a `worker.go` file with the following contents: | ||
```go title="worker.go" | ||
package main | ||
import ( | ||
"net/http" | ||
"github.com/vmware-labs/wasm-workers-server/kits/go/worker" | ||
) | ||
func main() { | ||
worker.ServeFunc(func(w http.ResponseWriter, r *http.Request) { | ||
w.Header().Set("x-generated-by", "wasm-workers-server") | ||
w.Write([]byte("Hello wasm!")) | ||
}) | ||
} | ||
``` | ||
1. Additionally, you can now go further add all the information from the received `http.Request`: | ||
```go title="worker.go" | ||
package main | ||
import ( | ||
"fmt" | ||
"io" | ||
"net/http" | ||
"github.com/vmware-labs/wasm-workers-server/kits/go/worker" | ||
) | ||
func main() { | ||
worker.ServeFunc(func(w http.ResponseWriter, r *http.Request) { | ||
var payload string | ||
reqBody, err := io.ReadAll(r.Body) | ||
if err != nil { | ||
panic(err) | ||
} | ||
r.Body.Close() | ||
if len(reqBody) == 0 { | ||
payload = "-" | ||
} else { | ||
payload = string(reqBody) | ||
} | ||
body := fmt.Sprintf("<!DOCTYPE html>"+ | ||
"<head>"+ | ||
"<title>Wasm Workers Server</title>"+ | ||
"<meta name=\"viewport\" content=\"width=device-width,initial-scale=1\">"+ | ||
"<meta charset=\"UTF-8\">"+ | ||
"<link rel=\"stylesheet\" href=\"https://cdn.jsdelivr.net/npm/water.css@2/out/water.css\">"+ | ||
"<style>"+ | ||
"body { max-width: 1000px; }"+ | ||
"main { margin: 5rem 0; }"+ | ||
"h1, p { text-align: center; }"+ | ||
"h1 { margin-bottom: 2rem; }"+ | ||
"pre { font-size: .9rem; }"+ | ||
"pre > code { padding: 2rem; }"+ | ||
"p { margin-top: 2rem; }"+ | ||
"</style>"+ | ||
"</head>"+ | ||
"<body>"+ | ||
"<main>"+ | ||
"<h1>Hello from Wasm Workers Server 👋</h1>"+ | ||
"<pre><code>Replying to %s<br>"+ | ||
"Method: %s<br>"+ | ||
"User Agent: %s<br>"+ | ||
"Payload: %s</code></pre>"+ | ||
"<p>"+ | ||
"This page was generated by a Go file running in WebAssembly."+ | ||
"</p>"+ | ||
"</main>"+ | ||
"</body>", r.URL.String(), r.Method, r.UserAgent(), payload) | ||
w.Header().Set("x-generated-by", "wasm-workers-server") | ||
w.Write([]byte(body)) | ||
}) | ||
} | ||
``` | ||
1. In this case, you need to compile the project to Wasm ([WASI](https://wasi.dev/)). To do this, make sure you have installed the TinyGo compiler by following the steps [here](https://tinygo.org/getting-started/install/): | ||
```bash | ||
tinygo build -o worker.wasm -target wasi worker.go | ||
``` | ||
1. Run your worker with `wws`. If you didn't download the `wws` server yet, check our [Getting Started](../get-started/quickstart.md) guide. | ||
```bash | ||
wws . | ||
⚙️ Loading routes from: . | ||
🗺 Detected routes: | ||
- http://127.0.0.1:8080/worker | ||
=> worker.wasm (name: default) | ||
🚀 Start serving requests at http://127.0.0.1:8080 | ||
``` | ||
1. Finally, open <http://127.0.0.1:8080/worker> in your browser. | ||
## Add a Key / Value store | ||
Wasm Workers allows you to add a Key / Value store to your workers. Read more information about this feature in the [Key / Value store](../features/key-value.md) section. | ||
To add a KV store to your worker, follow these steps: | ||
1. Create a new Go project: | ||
```bash | ||
go mod init worker-kv | ||
``` | ||
1. Add the Wasm Workers Server Go dependency | ||
``` | ||
go get -u github.com/vmware-labs/wasm-workers-server/kits/go/worker | ||
``` | ||
1. Create a `worker-kv.go` file with the following contents: | ||
```go title="worker-kv.go" | ||
package main | ||
import ( | ||
"net/http" | ||
"github.com/vmware-labs/wasm-workers-server/kits/go/worker" | ||
) | ||
func main() { | ||
worker.ServeFunc(func(w http.ResponseWriter, r *http.Request) { | ||
w.Header().Set("x-generated-by", "wasm-workers-server") | ||
w.Write([]byte("Hello wasm!")) | ||
}) | ||
} | ||
``` | ||
1. Then, let's read a value from the cache and update it: | ||
```go title="worker-kv.go" | ||
package main | ||
import ( | ||
"fmt" | ||
"net/http" | ||
"strconv" | ||
"github.com/vmware-labs/wasm-workers-server/kits/go/worker" | ||
) | ||
func main() { | ||
worker.ServeFunc(func(w http.ResponseWriter, r *http.Request) { | ||
cache, _ := r.Context().Value(worker.CacheKey).(map[string]string) | ||
var countNum uint32 | ||
if count, ok := cache["counter"]; ok { | ||
n, _ := strconv.ParseUint(count, 10, 32) | ||
countNum = uint32(n) | ||
} | ||
body := fmt.Sprintf("<!DOCTYPE html>"+ | ||
"<body>"+ | ||
"<h1>Key / Value store in Go</h1>"+ | ||
"<p>Counter: %d</p>"+ | ||
"<p>This page was generated by a Wasm module built from Go.</p>"+ | ||
"</body>", countNum) | ||
cache["counter"] = fmt.Sprintf("%d", countNum+1) | ||
w.Header().Set("x-generated-by", "wasm-workers-server") | ||
w.Write([]byte(body)) | ||
}) | ||
} | ||
``` | ||
1. Compile the project to Wasm ([WASI](https://wasi.dev/)): | ||
```bash | ||
tinygo build -o worker-kv.wasm -target wasi worker-kv.go | ||
``` | ||
1. Create a `worker-kv.toml` file with the following content. Note the name of the TOML file must match the name of the worker. In this case we have `worker-kv.wasm` and `worker-kv.toml` in the same folder: | ||
```toml title="worker-kv.toml" | ||
name = "workerkv" | ||
version = "1" | ||
[data] | ||
[data.kv] | ||
namespace = "workerkv" | ||
``` | ||
1. Run your worker with `wws`. If you didn't download the `wws` server yet, check our [Getting Started](../get-started/quickstart.md) guide. | ||
```bash | ||
wws . | ||
⚙️ Loading routes from: . | ||
🗺 Detected routes: | ||
- http://127.0.0.1:8080/worker-kv | ||
=> worker-kv.wasm (name: default) | ||
🚀 Start serving requests at http://127.0.0.1:8080 | ||
``` | ||
1. Finally, open <http://127.0.0.1:8080/worker-kv> in your browser. | ||
## Dynamic routes | ||
You can define [dynamic routes by adding route parameters to your worker files](../features/dynamic-routes.md) (like `[id].wasm`). To read them in Go, follow these steps: | ||
1. Use the `worker.ParamsKey` context value to read in the passed in parameters: | ||
```go title="main.go" | ||
package main | ||
import ( | ||
"fmt" | ||
"net/http" | ||
"github.com/vmware-labs/wasm-workers-server/kits/go/worker" | ||
) | ||
func main() { | ||
worker.ServeFunc(func(w http.ResponseWriter, r *http.Request) { | ||
params, _ := r.Context().Value(worker.ParamsKey).(map[string]string) | ||
... | ||
}) | ||
} | ||
``` | ||
1. Then, you can read the values as follows: | ||
```go title="main.go" | ||
package main | ||
import ( | ||
"fmt" | ||
"net/http" | ||
"github.com/vmware-labs/wasm-workers-server/kits/go/worker" | ||
) | ||
func main() { | ||
worker.ServeFunc(func(w http.ResponseWriter, r *http.Request) { | ||
params, _ := r.Context().Value(worker.ParamsKey).(map[string]string) | ||
id := "the value is not available" | ||
if val, ok := params["id"]; ok { | ||
id = val | ||
} | ||
w.Header().Set("x-generated-by", "wasm-workers-server") | ||
w.Write([]byte(fmt.Sprintf("Hey! The parameter is: %s", id))) | ||
}) | ||
} | ||
``` | ||
## Read environment variables | ||
Environment variables are configured [via the related TOML configuration file](../features/environment-variables.md). These variables are accessible via `os.Getenv` in your worker. To read them, just use the same name you configured in your TOML file: | ||
```toml title="envs.toml" | ||
name = "envs" | ||
version = "1" | ||
[vars] | ||
MESSAGE = "Hello 👋! This message comes from an environment variable" | ||
``` | ||
|
||
Now, you can read the `MESSAGE` variable using the [`os.Getenv`](https://pkg.go.dev/os#Getenv) function: | ||
|
||
```go title="envs.go" | ||
package main | ||
|
||
import ( | ||
"fmt" | ||
"net/http" | ||
"os" | ||
|
||
"github.com/vmware-labs/wasm-workers-server/kits/go/worker" | ||
) | ||
|
||
func main() { | ||
worker.ServeFunc(func(w http.ResponseWriter, r *http.Request) { | ||
body := fmt.Sprintf("The message is: %s", os.Getenv("MESSAGE")) | ||
|
||
w.Header().Set("x-generated-by", "wasm-workers-server") | ||
w.Write([]byte(body)) | ||
}) | ||
} | ||
|
||
``` | ||
|
||
If you prefer, you can configure the environment variable value dynamically by following [these instructions](../features/environment-variables.md#inject-existing-environment-variables). | ||
|
||
## Other examples | ||
|
||
* [Basic](https://github.com/vmware-labs/wasm-workers-server/tree/main/examples/go-basic) | ||
* [Counter](https://github.com/vmware-labs/wasm-workers-server/tree/main/examples/go-kv) | ||
|
||
The Go kit was originally authored by Mohammed Nafees ([@mnafees](https://github.com/mnafees)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.