Wasm

Use Wasm middleware in your HTTP pipeline

WebAssembly is a way to safely run code compiled in other languages. Runtimes execute WebAssembly Modules (Wasm), which are most often binaries with a .wasm extension.

The Wasm HTTP middleware allows you to manipulate an incoming request or serve a response with custom logic compiled to a Wasm binary. In other words, you can extend Dapr using external files that are not pre-compiled into the daprd binary. Dapr embeds wazero to accomplish this without CGO.

Wasm binaries are loaded from a URL. For example, the URL file://rewrite.wasm loads rewrite.wasm from the current directory of the process. On Kubernetes, see How to: Mount Pod volumes to the Dapr sidecar to configure a filesystem mount that can contain Wasm modules.

Component format

  1. apiVersion: dapr.io/v1alpha1
  2. kind: Component
  3. metadata:
  4. name: wasm
  5. spec:
  6. type: middleware.http.wasm
  7. version: v1
  8. metadata:
  9. - name: url
  10. value: "file://router.wasm"

Spec metadata fields

Minimally, a user must specify a Wasm binary implements the http-handler. How to compile this is described later.

FieldDetailsRequiredExample
urlThe URL of the resource including the Wasm binary to instantiate. The supported schemes include file://. The path of a file:// URL is relative to the Dapr process unless it begins with /.truefile://hello.wasm

Dapr configuration

To be applied, the middleware must be referenced in configuration. See middleware pipelines.

  1. apiVersion: dapr.io/v1alpha1
  2. kind: Configuration
  3. metadata:
  4. name: appconfig
  5. spec:
  6. httpPipeline:
  7. handlers:
  8. - name: wasm
  9. type: middleware.http.wasm

Note: WebAssembly middleware uses more resources than native middleware. This result in a resource constraint faster than the same logic in native code. Production usage should Control max concurrency.

Generating Wasm

This component lets you manipulate an incoming request or serve a response with custom logic compiled using the http-handler Application Binary Interface (ABI). The handle_request function receives an incoming request and can manipulate it or serve a response as necessary.

To compile your Wasm, you must compile source using a http-handler compliant guest SDK such as TinyGo.

Here’s an example in TinyGo:

  1. package main
  2. import (
  3. "strings"
  4. "github.com/http-wasm/http-wasm-guest-tinygo/handler"
  5. "github.com/http-wasm/http-wasm-guest-tinygo/handler/api"
  6. )
  7. func main() {
  8. handler.HandleRequestFn = handleRequest
  9. }
  10. // handleRequest implements a simple HTTP router.
  11. func handleRequest(req api.Request, resp api.Response) (next bool, reqCtx uint32) {
  12. // If the URI starts with /host, trim it and dispatch to the next handler.
  13. if uri := req.GetURI(); strings.HasPrefix(uri, "/host") {
  14. req.SetURI(uri[5:])
  15. next = true // proceed to the next handler on the host.
  16. return
  17. }
  18. // Serve a static response
  19. resp.Headers().Set("Content-Type", "text/plain")
  20. resp.Body().WriteString("hello")
  21. return // skip the next handler, as we wrote a response.
  22. }

If using TinyGo, compile as shown below and set the spec metadata field named “url” to the location of the output (for example, file://router.wasm):

  1. tinygo build -o router.wasm -scheduler=none --no-debug -target=wasi router.go`

Last modified June 19, 2023: Merge pull request #3565 from dapr/aacrawfi/skip-secrets-close (b1763bf)