http-wasm is HTTP client middleware implemented in WebAssembly. This is a TinyGo WASI library that implements the Guest ABI.
The following is an example of routing middleware:
package main
import (
"strings"
"github.com/httpwasm/http-wasm-guest-tinygo/handler"
"github.com/httpwasm/http-wasm-guest-tinygo/handler/api"
)
func main() {
handler.HandleRequestFn = handleRequest
}
// handle implements a simple HTTP router.
func handleRequest(req api.Request, resp api.Response) (next bool, reqCtx uint32) {
// If the URI starts with /host, trim it and dispatch to the next handler.
if uri := req.GetURI(); strings.HasPrefix(uri, "/host") {
req.SetURI(uri[5:])
next = true // proceed to the next handler on the host.
return
}
// Serve a static response
resp.Headers().Set("Content-Type", "text/plain")
resp.Body().WriteString("hello")
return // skip any handlers as the response is written.
}
If you make changes, you can rebuild this with TinyGo v0.28 or higher like so:
tinygo build -o examples/router/main.wasm -scheduler=none --no-debug -target=wasi examples/router/main.go
There are also more examples you may wish to try out!
The current maturity phase is early draft. Once this is integrated with coraza and dapr, we can begin discussions about compatability.
- 使用
//go:export
注解导出函数,httpwasm目前导出了两个函数handle_request
和handle_response
,
handleRequest
调用HandleRequestFn
handle_response
调用HandleResponseFn
// 代码在 ./handler/handler.go#20
// handleRequest is only exported to the host.
// wasm导出的函数,宿主host可以调用,使用 go:export 标记
//
//go:export handle_request
func handleRequest() (ctxNext uint64) { //nolint
next, reqCtx := HandleRequestFn(wasmRequest{}, wasmResponse{})
}
// handleResponse is only exported to the host.
// wasm导出的函数,宿主host可以调用,使用 go:export 标记
//
//go:export handle_response
func handleResponse(reqCtx uint32, isError uint32) { //nolint
HandleResponseFn(reqCtx, wasmRequest{}, wasmResponse{}, isErrorB)
}
- 在wasm的main函数中指定
HandleRequestFn
和HandleResponseFn
的实现. host-->guest.handle_request-->HandleRequestFn-->具体实现
func main() {
handler.HandleRequestFn = handleRequest
}
// handleRequest implements a simple HTTP router.
func handleRequest(req api.Request, resp api.Response) (next bool, reqCtx uint32) {
}
HandleRequestFn
有 api.Request
和 api.Response
两个接口参数,用来绑定host的request和reponse,下面说下如何实现
api.Request
接口实现是wasmRequest
,api.Response
接口实现是wasmResponse
.实现再调用host 导入的函数,根据指定的数据格式进行交换,所以 wasm 默认不能处理并发请求.
- 导入host函数
复杂的逻辑可以放到host端完成,通过imports导入函数,由guest wasm进行调用host的实现,主要通过指针地址和数据长度,完成数据交换
所有的函数名均为 小写 下划线进行连接,详见:https://http-wasm.io/rationale/#why-is-everything-lower_snake_case-instead-of-lower-hyphen-case
./handler/internal/imports/imports.go
中,使用//go:build tinygo.wasm
标识tinygo编译,以本次新增的方法为例
//go:wasmimport http_handler get_template
func getTemplate(ptr uint32, limit BufLimit) (len uint32)
//go:wasmimport http_handler set_template
func setTemplate(ptr, size uint32)
//go:wasmimport http_handler get_template
wasm的模块名称是http_handler
,host加载wasm的二进制文件,初始化模块名称时需要指定为http_handler
,host的import导入函数,名称为 get_template