227 lines
5.5 KiB
Go
227 lines
5.5 KiB
Go
// Package main provides a hello-world WASM plugin example for Bifrost.
|
|
// This plugin demonstrates the basic structure and exports required for WASM plugins.
|
|
//
|
|
// Build with TinyGo:
|
|
//
|
|
// tinygo build -o build/hello-world.wasm -target=wasi -scheduler=none main.go
|
|
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
)
|
|
|
|
// ============================================================================
|
|
// Plugin Exports
|
|
// ============================================================================
|
|
|
|
//export get_name
|
|
func get_name() uint64 {
|
|
return writeBytes([]byte("Hello World WASM Plugin"))
|
|
}
|
|
|
|
//export init
|
|
func init_plugin(configPtr, configLen uint32) int32 {
|
|
println("WASM Plugin: Init called")
|
|
if configLen > 0 {
|
|
configData := readInput(configPtr, configLen)
|
|
println("WASM Plugin: Config received:", string(configData))
|
|
}
|
|
return 0
|
|
}
|
|
|
|
//export http_intercept
|
|
func http_intercept(inputPtr, inputLen uint32) uint64 {
|
|
println("WASM Plugin: http_intercept called")
|
|
|
|
inputData := readInput(inputPtr, inputLen)
|
|
if inputData == nil {
|
|
return writeError("no input data")
|
|
}
|
|
|
|
// Parse input
|
|
var input HTTPInterceptInput
|
|
if err := json.Unmarshal(inputData, &input); err != nil {
|
|
println("WASM Plugin: parse error:", err.Error())
|
|
return writeError("parse error: " + err.Error())
|
|
}
|
|
|
|
// Log parsed data
|
|
println("WASM Plugin: HTTP", input.Request.Method, input.Request.Path)
|
|
if ct, ok := input.Request.Headers["content-type"]; ok {
|
|
println("WASM Plugin: Content-Type:", ct)
|
|
}
|
|
input.Context["from-http"] = "123"
|
|
// Return pass-through
|
|
output := HTTPInterceptOutput{
|
|
Context: input.Context,
|
|
Request: input.Request,
|
|
HasResponse: false,
|
|
Error: "",
|
|
}
|
|
|
|
data, _ := json.Marshal(output)
|
|
return writeBytes(data)
|
|
}
|
|
|
|
//export pre_hook
|
|
func pre_hook(inputPtr, inputLen uint32) uint64 {
|
|
println("WASM Plugin: pre_hook called")
|
|
|
|
inputData := readInput(inputPtr, inputLen)
|
|
if inputData == nil {
|
|
return writePreHookError("no input data")
|
|
}
|
|
|
|
println("WASM Plugin: Pre-hook input:", string(inputData))
|
|
|
|
// Parse input
|
|
var input PreHookInput
|
|
if err := json.Unmarshal(inputData, &input); err != nil {
|
|
println("WASM Plugin: parse error:", err.Error())
|
|
return writePreHookError("parse error: " + err.Error())
|
|
}
|
|
|
|
// Print existing context
|
|
for k, v := range input.Context {
|
|
println("WASM Plugin: Context", k, "=", v)
|
|
}
|
|
|
|
input.Context["from-pre-hook"] = "789"
|
|
|
|
// Return with custom context value
|
|
output := PreHookOutput{
|
|
Context: input.Context,
|
|
Request: input.Request,
|
|
HasShortCircuit: false,
|
|
Error: "",
|
|
}
|
|
|
|
data, _ := json.Marshal(output)
|
|
return writeBytes(data)
|
|
}
|
|
|
|
//export post_hook
|
|
func post_hook(inputPtr, inputLen uint32) uint64 {
|
|
println("WASM Plugin: post_hook called")
|
|
|
|
inputData := readInput(inputPtr, inputLen)
|
|
if inputData == nil {
|
|
return writePostHookError("no input data")
|
|
}
|
|
|
|
// Parse input
|
|
var input PostHookInput
|
|
if err := json.Unmarshal(inputData, &input); err != nil {
|
|
println("WASM Plugin: parse error:", err.Error())
|
|
return writePostHookError("parse error: " + err.Error())
|
|
}
|
|
|
|
println("WASM Plugin: Post-hook input:", string(inputData))
|
|
// Print existing context
|
|
for k, v := range input.Context {
|
|
println("WASM Plugin: Context", k, "=", v)
|
|
}
|
|
|
|
// Parse response for logging
|
|
|
|
if processed, ok := input.Context["wasm_plugin_processed"].(bool); ok && processed {
|
|
println("WASM Plugin: Pre-hook context value present")
|
|
}
|
|
|
|
input.Context["from-post-hook"] = "456"
|
|
// Return pass-through
|
|
output := PostHookOutput{
|
|
Context: input.Context,
|
|
Response: input.Response,
|
|
Error: input.Error,
|
|
HasError: false,
|
|
HookError: "",
|
|
}
|
|
|
|
data, _ := json.Marshal(output)
|
|
return writeBytes(data)
|
|
}
|
|
|
|
//export http_stream_chunk_hook
|
|
func http_stream_chunk_hook(inputPtr, inputLen uint32) uint64 {
|
|
println("WASM Plugin: http_stream_chunk_hook called")
|
|
|
|
inputData := readInput(inputPtr, inputLen)
|
|
if inputData == nil {
|
|
return writeStreamChunkError("no input data")
|
|
}
|
|
|
|
// Parse input
|
|
var input HTTPStreamChunkHookInput
|
|
if err := json.Unmarshal(inputData, &input); err != nil {
|
|
println("WASM Plugin: parse error:", err.Error())
|
|
return writeStreamChunkError("parse error: " + err.Error())
|
|
}
|
|
|
|
println("WASM Plugin: Stream chunk received")
|
|
|
|
// Add context value
|
|
input.Context["from-stream-chunk"] = "wasm-plugin"
|
|
|
|
// Pass through chunk unchanged
|
|
output := HTTPStreamChunkHookOutput{
|
|
Context: input.Context,
|
|
Chunk: input.Chunk,
|
|
HasChunk: true,
|
|
Skip: false,
|
|
Error: "",
|
|
}
|
|
|
|
data, _ := json.Marshal(output)
|
|
return writeBytes(data)
|
|
}
|
|
|
|
//export cleanup
|
|
func cleanup() int32 {
|
|
println("WASM Plugin: Cleanup called")
|
|
return 0
|
|
}
|
|
|
|
// Helper functions for error responses
|
|
func writeError(msg string) uint64 {
|
|
output := HTTPInterceptOutput{HasResponse: false, Error: msg}
|
|
data, _ := json.Marshal(output)
|
|
return writeBytes(data)
|
|
}
|
|
|
|
func writePreHookError(msg string) uint64 {
|
|
output := PreHookOutput{
|
|
Context: map[string]interface{}{},
|
|
Request: nil,
|
|
HasShortCircuit: false,
|
|
Error: msg,
|
|
}
|
|
data, _ := json.Marshal(output)
|
|
return writeBytes(data)
|
|
}
|
|
|
|
func writePostHookError(msg string) uint64 {
|
|
output := PostHookOutput{
|
|
Context: map[string]interface{}{},
|
|
Response: nil,
|
|
HasError: false,
|
|
HookError: msg,
|
|
}
|
|
data, _ := json.Marshal(output)
|
|
return writeBytes(data)
|
|
}
|
|
|
|
func writeStreamChunkError(msg string) uint64 {
|
|
output := HTTPStreamChunkHookOutput{
|
|
Context: map[string]interface{}{},
|
|
Chunk: nil,
|
|
HasChunk: false,
|
|
Skip: false,
|
|
Error: msg,
|
|
}
|
|
data, _ := json.Marshal(output)
|
|
return writeBytes(data)
|
|
}
|
|
|
|
func main() {}
|