Repository navigation
Expand file tree
/
Copy pathmain.go
More file actions
213 lines (187 loc) · 5.38 KB
/
Copy pathmain.go
File metadata and controls
213 lines (187 loc) · 5.38 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
// echo is the goblog wasm test fixture: it implements every export of the
// host contract in the most literal way so the adapter can be tested.
package main
import (
"crypto/rand"
"encoding/hex"
"encoding/json"
"strings"
"time"
pdk "github.com/extism/go-pdk"
)
//go:wasmimport extism:host/user store_get
func hostStoreGet(uint64) uint64
//go:wasmimport extism:host/user store_set
func hostStoreSet(uint64, uint64) uint64
//go:wasmimport extism:host/user store_delete
func hostStoreDelete(uint64) uint64
//go:wasmimport extism:host/user store_list
func hostStoreList(uint64) uint64
// storeGetOK returns the value and whether the key exists: the host returns
// offset 0 (Extism's null) for a missing key.
func storeGetOK(key string) (string, bool) {
k := pdk.AllocateString(key)
defer k.Free()
ptr := hostStoreGet(k.Offset())
if ptr == 0 {
return "", false
}
return pdk.ParamString(ptr), true
}
func storeGet(key string) string {
v, _ := storeGetOK(key)
return v
}
func storeSet(key, value string) {
k := pdk.AllocateString(key)
defer k.Free()
v := pdk.AllocateString(value)
defer v.Free()
hostStoreSet(k.Offset(), v.Offset())
}
func storeDelete(key string) {
k := pdk.AllocateString(key)
defer k.Free()
hostStoreDelete(k.Offset())
}
func storeList(prefix string) string {
p := pdk.AllocateString(prefix)
defer p.Free()
return pdk.ParamString(hostStoreList(p.Offset()))
}
type ctx struct {
Settings map[string]string `json:"settings"`
Template string `json:"template"`
Request struct {
Path string `json:"path"`
SubPath string `json:"sub_path"`
Query map[string]string `json:"query"`
Method string `json:"method"`
} `json:"request"`
}
func readCtx() ctx {
var c ctx
json.Unmarshal(pdk.Input(), &c)
return c
}
func out(v any) int32 {
b, _ := json.Marshal(v)
pdk.Output(b)
return 0
}
//go:wasmexport identity
func identity() int32 {
return out(map[string]string{"name": "echo", "display_name": "Echo", "version": "1.2.3"})
}
//go:wasmexport settings
func settings() int32 {
return out([]map[string]string{
{"key": "enabled", "type": "text", "default": "true", "label": "Enabled", "description": "on/off"},
{"key": "greeting", "type": "text", "default": "hi", "label": "Greeting", "description": "footer text"},
})
}
//go:wasmexport pages
func pages() int32 {
return out([]map[string]any{{"page_type": "echo", "title": "Echo", "slug": "echo", "show_in_nav": true, "nav_order": 5, "description": "echo page"}})
}
//go:wasmexport jobs
func jobs() int32 {
return out([]map[string]any{{"name": "tick", "interval_seconds": 60}})
}
//go:wasmexport template_footer
func templateFooter() int32 {
c := readCtx()
pdk.OutputString("<p>" + c.Settings["greeting"] + "</p>")
return 0
}
//go:wasmexport template_head
func templateHead() int32 {
pdk.OutputString("<!-- echo head -->")
return 0
}
//go:wasmexport template_data
func templateData() int32 {
c := readCtx()
return out(map[string]any{"greeting": c.Settings["greeting"], "template": c.Template})
}
//go:wasmexport render_page
func renderPage() int32 {
c := readCtx()
switch c.Request.SubPath {
case "":
return out(map[string]any{"html": "<h2>echo</h2>" + c.Settings["greeting"]})
case "data.json":
return out(map[string]any{"raw": map[string]any{"status": 200, "content_type": "application/json", "body": `{"ok":true}`}})
case "tmpl":
return out(map[string]any{"template": "page_content.html", "data": map[string]any{"plugin_content": "from template", "has_plugin_content": true}})
case "store":
storeSet("k", "v-"+c.Request.Query["v"])
got := storeGet("k")
keys := storeList("")
storeDelete("k")
after, found := storeGetOK("k")
if !found {
after = "missing"
}
return out(map[string]any{"html": "got=" + got + " keys=" + keys + " after=[" + after + "]"})
case "raw-badstatus":
return out(map[string]any{"raw": map[string]any{"status": 5, "body": "x"}})
case "raw-defaults":
return out(map[string]any{"raw": map[string]any{"body": "plain"}})
case "now":
return out(map[string]any{"html": itoa(int(time.Now().Unix()))})
case "rand":
b := make([]byte, 16)
rand.Read(b)
return out(map[string]any{"html": hex.EncodeToString(b)})
case "http":
req := pdk.NewHTTPRequest(pdk.MethodGet, c.Request.Query["url"])
resp := req.Send()
return out(map[string]any{"html": "status=" + itoa(int(resp.Status())) + " body=" + string(resp.Body())})
case "log":
pdk.Log(pdk.LogInfo, "hello from echo")
return out(map[string]any{"html": "logged"})
case "spin":
for {
}
case "big":
b := make([]byte, 200<<20)
return out(map[string]any{"html": itoa(len(b))})
case "boom":
pdk.SetErrorString("kaboom")
return 1
}
return out(map[string]any{})
}
//go:wasmexport run_job
func runJob() int32 {
var in struct {
Name string `json:"name"`
Settings map[string]string `json:"settings"`
}
json.Unmarshal(pdk.Input(), &in)
storeSet("job_ran", in.Name+"/"+in.Settings["greeting"])
return out(map[string]any{})
}
//go:wasmexport on_init
func onInit() int32 {
var in struct {
Settings map[string]string `json:"settings"`
}
json.Unmarshal(pdk.Input(), &in)
storeSet("init", "1")
storeSet("init_greeting", in.Settings["greeting"])
return out(map[string]any{})
}
func itoa(n int) string {
if n == 0 {
return "0"
}
var b []byte
for n > 0 {
b = append([]byte{byte('0' + n%10)}, b...)
n /= 10
}
return strings.TrimLeft(string(b), " ")
}
func main() {}