Skip to content

Commit d4d8822

Browse files
committed
split Go SDK into its own repo
Signed-off-by: Joel Dice <[email protected]>
1 parent a5c1f3c commit d4d8822

File tree

63 files changed

+1208
-10
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

63 files changed

+1208
-10
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
1+
.spin
2+
main.wasm
13
*/sdk-version-go.c

Makefile

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
VERSION = 2.3.0-pre0
2+
13
# ----------------------------------------------------------------------
24
# Test
35
# ----------------------------------------------------------------------
@@ -17,7 +19,7 @@ http/testdata/http-tinygo/main.wasm: http/testdata/http-tinygo/main.go
1719
# ----------------------------------------------------------------------
1820
# Build examples
1921
# ----------------------------------------------------------------------
20-
EXAMPLES_DIR = ../../examples
22+
EXAMPLES_DIR = examples
2123

2224
.PHONY: build-examples
2325
build-examples: generate
@@ -70,9 +72,8 @@ generate: $(GENERATED_OUTBOUND_MYSQL) $(GENERATED_OUTBOUND_PG)
7072
generate: $(SDK_VERSION_DEST_FILES)
7173

7274
$(SDK_VERSION_DEST_FILES): $(SDK_VERSION_SOURCE_FILE)
73-
export version="$$(cd ../rust && cargo run)"; \
7475
export commit="$$(git rev-parse HEAD)"; \
75-
sed -e "s/{{VERSION}}/$${version}/" -e "s/{{COMMIT}}/$${commit}/" < $< > $@
76+
sed -e "s/{{VERSION}}/${VERSION}/" -e "s/{{COMMIT}}/$${commit}/" < $< > $@
7677

7778
$(GENERATED_SPIN_VARIABLES):
7879
wit-bindgen c --import wit/spin-config.wit --out-dir ./variables
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
# Making outbound HTTP requests from TinyGo Spin components
2+
3+
The TinyGo SDK for building Spin components allows us to granularly allow
4+
components to send HTTP requests to certain hosts. This is configured in
5+
`spin.toml`.
6+
7+
> For more information and examples for using TinyGo with WebAssembly, check
8+
> [the official TinyGo documentation](https://tinygo.org/docs/guides/webassembly/)
9+
> and
10+
> [the Wasm examples](https://github.com/tinygo-org/tinygo/tree/release/src/examples/wasm).
11+
12+
Creating and sending HTTP requests from Spin components closely follows the Go
13+
`net/http` API. See [tinygo-hello/main.go](./tinygo-hello/main.go).
14+
15+
Building this as a WebAssembly module can be done using the `tinygo` compiler:
16+
17+
```shell
18+
$ spin build
19+
Building component outbound-http-to-same-app with `tinygo build -target=wasi -gc=leaking -no-debug -o main.wasm main.go`
20+
Working directory: "./outbound-http-to-same-app"
21+
Building component tinygo-hello with `tinygo build -target=wasi -gc=leaking -no-debug -o main.wasm main.go`
22+
Working directory: "./tinygo-hello"
23+
Finished building all Spin components
24+
```
25+
26+
The component configuration must contain a list of all hosts allowed to send
27+
HTTP requests to, otherwise sending the request results in an error:
28+
29+
```
30+
Cannot send HTTP request: Destination not allowed: <URL>
31+
```
32+
33+
The `tinygo-hello` component has the following allowed hosts set:
34+
35+
```toml
36+
[component.tinygo-hello]
37+
source = "tinygo-hello/main.wasm"
38+
allowed_outbound_hosts = [
39+
"https://random-data-api.fermyon.app",
40+
"https://postman-echo.com",
41+
]
42+
```
43+
44+
And the `outbound-http-to-same-app` uses the dedicated `self` keyword to enable making
45+
a request to another component in this same app, via a relative path (in this case, the component
46+
is `tinygo-hello` at `/hello`):
47+
48+
```toml
49+
[component.outbound-http-to-same-app]
50+
source = "outbound-http-to-same-app/main.wasm"
51+
# Use self to make outbound requests to components in the same Spin application.
52+
allowed_outbound_hosts = ["http://self"]
53+
```
54+
55+
At this point, we can execute the application with the `spin` CLI:
56+
57+
```shell
58+
$ RUST_LOG=spin=trace,wasi_outbound_http=trace spin up
59+
```
60+
61+
The application can now receive requests on `http://localhost:3000/hello`:
62+
63+
```shell
64+
$ curl -i localhost:3000/hello -X POST -d "hello there"
65+
HTTP/1.1 200 OK
66+
content-length: 976
67+
date: Thu, 26 Oct 2023 18:26:17 GMT
68+
69+
{{"timestamp":1698344776965,"fact":"Reindeer grow new antlers every year"}}
70+
...
71+
```
72+
73+
As well as via the `/outbound-http-to-same-app` path to verify outbound http to the `tinygo-hello` component:
74+
75+
```shell
76+
$ curl -i localhost:3000/outbound-http-to-same-app
77+
HTTP/1.1 200 OK
78+
content-length: 946
79+
date: Thu, 26 Oct 2023 18:26:53 GMT
80+
81+
{{{"timestamp":1698344813408,"fact":"Some hummingbirds weigh less than a penny"}}
82+
...
83+
```
84+
85+
## Notes
86+
87+
- this only implements sending HTTP/1.1 requests
88+
- requests are currently blocking and synchronous
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
module outbound-http-to-same-app
2+
3+
go 1.20
4+
5+
require github.com/fermyon/spin/sdk/go/v2 v2.0.0
6+
7+
require github.com/julienschmidt/httprouter v1.3.0 // indirect
8+
9+
replace github.com/fermyon/spin/sdk/go/v2 v2.0.0 => ../../../
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U=
2+
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"net/http"
6+
7+
spinhttp "github.com/fermyon/spin/sdk/go/v2/http"
8+
)
9+
10+
func init() {
11+
spinhttp.Handle(func(w http.ResponseWriter, r *http.Request) {
12+
// Because we included self in `allowed_http_hosts`, we can make outbound
13+
// HTTP requests to our own app using a relative path.
14+
resp, err := spinhttp.Get("/hello")
15+
if err != nil {
16+
http.Error(w, err.Error(), http.StatusInternalServerError)
17+
return
18+
}
19+
20+
fmt.Fprintln(w, resp.Body)
21+
fmt.Fprintln(w, resp.Header.Get("content-type"))
22+
})
23+
}
24+
25+
func main() {}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
spin_manifest_version = 2
2+
3+
[application]
4+
authors = ["Fermyon Engineering <[email protected]>"]
5+
description = "A simple Spin application written in (Tiny)Go that performs outbound HTTP requests."
6+
name = "spin-tinygo-outbound-http"
7+
version = "1.0.0"
8+
9+
[[trigger.http]]
10+
route = "/hello"
11+
component = "tinygo-hello"
12+
13+
[[trigger.http]]
14+
route = "/outbound-http-to-same-app"
15+
component = "outbound-http-to-same-app"
16+
17+
[component.tinygo-hello]
18+
source = "tinygo-hello/main.wasm"
19+
allowed_outbound_hosts = [
20+
"https://random-data-api.fermyon.app:443",
21+
"https://postman-echo.com:443",
22+
]
23+
[component.tinygo-hello.build]
24+
workdir = "tinygo-hello"
25+
command = "tinygo build -target=wasi -gc=leaking -no-debug -o main.wasm main.go"
26+
27+
[component.outbound-http-to-same-app]
28+
source = "outbound-http-to-same-app/main.wasm"
29+
# Use self to make outbound requests to components in the same Spin application.
30+
allowed_outbound_hosts = ["http://self"]
31+
[component.outbound-http-to-same-app.build]
32+
workdir = "outbound-http-to-same-app"
33+
command = "tinygo build -target=wasi -gc=leaking -no-debug -o main.wasm main.go"
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
module github.com/fermyon/spin/templates/spin-http-tinygo-outbound-http
2+
3+
go 1.20
4+
5+
require github.com/fermyon/spin/sdk/go/v2 v2.0.0
6+
7+
require github.com/julienschmidt/httprouter v1.3.0 // indirect
8+
9+
replace github.com/fermyon/spin/sdk/go/v2 v2.0.0 => ../../../
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U=
2+
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package main
2+
3+
import (
4+
"bytes"
5+
"fmt"
6+
"net/http"
7+
"os"
8+
9+
spinhttp "github.com/fermyon/spin/sdk/go/v2/http"
10+
)
11+
12+
func init() {
13+
spinhttp.Handle(func(w http.ResponseWriter, r *http.Request) {
14+
r1, err := spinhttp.Get("https://random-data-api.fermyon.app/animals/json")
15+
if err != nil {
16+
http.Error(w, err.Error(), http.StatusInternalServerError)
17+
return
18+
}
19+
20+
fmt.Fprintln(w, r1.Body)
21+
fmt.Fprintln(w, r1.Header.Get("content-type"))
22+
23+
r2, err := spinhttp.Post("https://postman-echo.com/post", "text/plain", r.Body)
24+
if err != nil {
25+
http.Error(w, err.Error(), http.StatusInternalServerError)
26+
return
27+
}
28+
fmt.Fprintln(w, r2.Body)
29+
30+
req, err := http.NewRequest("PUT", "https://postman-echo.com/put", bytes.NewBufferString("General Kenobi!"))
31+
if err != nil {
32+
http.Error(w, err.Error(), http.StatusInternalServerError)
33+
return
34+
}
35+
req.Header.Add("foo", "bar")
36+
r3, err := spinhttp.Send(req)
37+
if err != nil {
38+
http.Error(w, err.Error(), http.StatusInternalServerError)
39+
return
40+
}
41+
42+
fmt.Fprintln(w, r3.Body)
43+
44+
// `spin.toml` is not configured to allow outbound HTTP requests to this host,
45+
// so this request will fail.
46+
if _, err := spinhttp.Get("https://fermyon.com"); err != nil {
47+
fmt.Fprintf(os.Stderr, "Cannot send HTTP request: %v", err)
48+
}
49+
})
50+
}
51+
52+
func main() {}

0 commit comments

Comments
 (0)