Skip to content

Commit d7c7c4f

Browse files
committed
feat(sdk): add support for http trigger with wasip2 support
Signed-off-by: Rajat Jindal <[email protected]>
1 parent 92d0b8d commit d7c7c4f

File tree

316 files changed

+26692
-0
lines changed

Some content is hidden

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

316 files changed

+26692
-0
lines changed

.github/workflows/pr.yaml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
name: Run Integration tests
2+
on:
3+
push:
4+
branches:
5+
- wasip2-http
6+
7+
workflow_dispatch: {}
8+
9+
jobs:
10+
build:
11+
runs-on: ubuntu-latest
12+
steps:
13+
- uses: actions/checkout@v4
14+
15+
- name: Setup Go
16+
uses: actions/setup-go@v5
17+
with:
18+
go-version: '1.23'
19+
20+
- name: Setup TinyGo
21+
uses: acifani/setup-tinygo@v2
22+
with:
23+
tinygo-version: '0.33.0'
24+
25+
- name: Setup Spin
26+
uses: fermyon/actions/spin/setup@v1
27+
with:
28+
version: "v2.7.0"
29+
30+
- name: Run wasip2 integration tests
31+
run: make test-integration-wasip2
32+

Makefile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ test: test-integration
1212
test-integration: http/testdata/http-tinygo/main.wasm
1313
go test -v -count=1 .
1414

15+
.PHONY: test-integration-wasip2
16+
test-integration-wasip2:
17+
cd v2 && go test -v -count=1 .
18+
1519
http/testdata/http-tinygo/main.wasm: generate
1620
http/testdata/http-tinygo/main.wasm: http/testdata/http-tinygo/main.go
1721
tinygo build -target=wasi -gc=leaking -no-debug -o http/testdata/http-tinygo/main.wasm http/testdata/http-tinygo/main.go

v2/README.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
WIP
2+
3+
spin-go-sdk with wasip2 support
4+
5+
Notes:
6+
7+
The current version of tooling used for this work:
8+
9+
- ydnar/wasm-tools-go `a45ed842846a419a5efd02b9384e14417cc90817`
10+
- wasm-tools `wasm-tools 1.216.0 (28c8962b1 2024-08-22)`
11+
- tinygo version 0.33.0 darwin/arm64 (using go version go1.22.6 and LLVM version 18.1.2)
12+
- spin 2.8.0-pre0 (74d3517 2024-08-30)
13+

v2/examples/http/go.mod

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
module github.com/fermyon/spin-go-sdk/v2/examples/http
2+
3+
go 1.23.2
4+
5+
require github.com/fermyon/spin-go-sdk/v2 v2.0.0
6+
7+
require (
8+
github.com/julienschmidt/httprouter v1.3.0 // indirect
9+
go.bytecodealliance.org v0.4.0 // indirect
10+
)
11+
12+
replace github.com/fermyon/spin-go-sdk/v2 => ../../

v2/examples/http/go.sum

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U=
2+
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
3+
go.bytecodealliance.org v0.4.0 h1:SRwgZIcXR54AmbJg9Y3AMgDlZlvD8dffteBYW+nCD3k=
4+
go.bytecodealliance.org v0.4.0/go.mod h1:hkdjfgQ/bFZYUucnm9cn0Q8/SHO3iT0rzskYlkV4Jy0=

v2/examples/http/main.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"net/http"
6+
7+
spinhttp "github.com/fermyon/spin-go-sdk/v2/http"
8+
)
9+
10+
func init() {
11+
spinhttp.Handle(func(w http.ResponseWriter, r *http.Request) {
12+
w.Header().Set("Content-Type", "text/plain")
13+
w.Header().Set("foo", "bar")
14+
15+
w.WriteHeader(http.StatusOK)
16+
fmt.Fprintln(w, "== RESPONSE ==")
17+
fmt.Fprintln(w, "Hello Fermyon!")
18+
fmt.Fprintln(w, "Hello again Fermyon!")
19+
})
20+
}
21+
22+
func main() {}

v2/examples/http/spin.toml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
spin_manifest_version = 2
2+
3+
[application]
4+
authors = ["Rajat Jindal <[email protected]>"]
5+
description = "A simple Spin application written in (Tiny)Go."
6+
name = "hello-example"
7+
version = "1.0.0"
8+
9+
[[trigger.http]]
10+
route = "/hello"
11+
component = "hello"
12+
13+
[component.hello]
14+
source = "main.wasm"
15+
[component.hello.build]
16+
command = "tinygo build -target=wasip2 --wit-package $(go list -mod=readonly -m -f '{{.Dir}}' github.com/fermyon/spin-go-sdk/v2)/wit --wit-world http-trigger -gc=leaking -no-debug -o main.wasm main.go"

v2/go.mod

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
module github.com/fermyon/spin-go-sdk/v2
2+
3+
go 1.23.2
4+
5+
require (
6+
github.com/julienschmidt/httprouter v1.3.0
7+
go.bytecodealliance.org v0.4.0
8+
)

v2/go.sum

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U=
2+
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
3+
go.bytecodealliance.org v0.4.0 h1:SRwgZIcXR54AmbJg9Y3AMgDlZlvD8dffteBYW+nCD3k=
4+
go.bytecodealliance.org v0.4.0/go.mod h1:hkdjfgQ/bFZYUucnm9cn0Q8/SHO3iT0rzskYlkV4Jy0=

v2/http/client.go

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
package http
2+
3+
import (
4+
"fmt"
5+
"io"
6+
"net/http"
7+
8+
outgoinghandler "github.com/fermyon/spin-go-sdk/v2/internal/wasi/http/v0.2.0/outgoing-handler"
9+
"github.com/fermyon/spin-go-sdk/v2/internal/wasi/http/v0.2.0/types"
10+
"go.bytecodealliance.org/cm"
11+
)
12+
13+
// NewTransport returns http.RoundTripper backed by Spin SDK
14+
func NewTransport() http.RoundTripper {
15+
return &Transport{}
16+
}
17+
18+
// Transport implements http.RoundTripper
19+
type Transport struct{}
20+
21+
// RoundTrip makes roundtrip using Spin SDK
22+
func (r *Transport) RoundTrip(req *http.Request) (*http.Response, error) {
23+
return Send(req)
24+
}
25+
26+
// NewClient returns a new HTTP client compatible with the Spin SDK
27+
func NewClient() *http.Client {
28+
return &http.Client{
29+
Transport: &Transport{},
30+
}
31+
}
32+
33+
func Send(req *http.Request) (*http.Response, error) {
34+
or, err := NewOutgoingHttpRequest(req)
35+
if err != nil {
36+
return nil, err
37+
}
38+
39+
result := outgoinghandler.Handle(or, cm.None[types.RequestOptions]())
40+
if result.Err() != nil {
41+
return nil, fmt.Errorf("TODO: convert to readable error")
42+
}
43+
44+
if result.IsErr() {
45+
return nil, fmt.Errorf("error is %v", result.Err())
46+
}
47+
48+
okresult := result.OK()
49+
50+
//wait until resp is returned
51+
okresult.Subscribe().Block()
52+
53+
incomingResp := okresult.Get()
54+
if incomingResp.None() {
55+
return nil, fmt.Errorf("incoming resp is None")
56+
}
57+
58+
if incomingResp.Some().IsErr() {
59+
return nil, fmt.Errorf("error is %v", incomingResp.Some().Err())
60+
}
61+
62+
if incomingResp.Some().OK().IsErr() {
63+
return nil, fmt.Errorf("error is %v", incomingResp.Some().OK().Err())
64+
}
65+
66+
okresp := incomingResp.Some().OK().OK()
67+
var body io.ReadCloser
68+
if consumeResult := okresp.Consume(); consumeResult.IsErr() {
69+
return nil, fmt.Errorf("failed to consume incoming request %s", *consumeResult.Err())
70+
} else if streamResult := consumeResult.OK().Stream(); streamResult.IsErr() {
71+
return nil, fmt.Errorf("failed to consume incoming requests's stream %s", streamResult.Err())
72+
} else {
73+
body = NewReadCloser(*streamResult.OK())
74+
}
75+
76+
resp := &http.Response{
77+
StatusCode: int(okresp.Status()),
78+
Body: body,
79+
}
80+
81+
return resp, nil
82+
}
83+
84+
func Get(url string) (*http.Response, error) {
85+
req, err := http.NewRequest(http.MethodGet, url, nil)
86+
if err != nil {
87+
return nil, err
88+
}
89+
90+
return Send(req)
91+
}
92+
93+
func Post(url string, contentType string, body io.Reader) (*http.Response, error) {
94+
req, err := http.NewRequest(http.MethodPost, url, body)
95+
if err != nil {
96+
return nil, err
97+
}
98+
99+
if contentType != "" {
100+
req.Header.Set("Content-Type", contentType)
101+
}
102+
103+
return Send(req)
104+
}

0 commit comments

Comments
 (0)