Skip to content

Load a WebAssembly module into the HTTP filter chain: the wasm build feature, the filter config, plugin configuration, and instance lifecycle.

requires: wasm

The wasm HTTP filter loads a WebAssembly module into the proxy and calls it on every request and response passing through the filter chain. Use it when you need custom logic in-process — header and body mutation, bespoke auth, callouts — without forking or rebuilding Arion.

Before you begin

  • Arion must be built with the wasm Cargo feature (cargo build -p arion-proxy --features wasm). A binary without it refuses to start when the config contains a wasm filter.
  • You need a compiled plugin — a .wasm module built with the Rust SDK for the wasm32-unknown-unknown target.

Enable it

Add the filter to http_filters in the HTTP connection manager, before the router:

http_filters:
  - name: envoy.filters.http.wasm
    typed_config:
      "@type": type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm
      config:
        name: auth_filter
        root_id: auth_filter
        vm_config:
          runtime: envoy.wasm.runtime.v8
          code:
            local:
              filename: /etc/arion/auth_filter.wasm
  - name: envoy.filters.http.router
    typed_config:
      "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router

config.name and root_id identify the plugin. runtime is accepted for Envoy compatibility but its value is not used — Arion always runs modules on its embedded Wasmtime engine. vm_config.vm_id and allow_precompiled are optional. code takes a local data source: filename (a .wasm file), inline_bytes (base64 module bytes), or inline_string (WAT text).

Variations

Pass configuration to the plugin

configuration carries an arbitrary string (typically JSON) that the plugin reads at startup with get_plugin_config(). It must be wrapped as a google.protobuf.StringValue:

config:
  name: auth_filter
  root_id: auth_filter
  configuration:
    "@type": type.googleapis.com/google.protobuf.StringValue
    value: '{"header": "x-tenant", "required": true}'
  vm_config:
    runtime: envoy.wasm.runtime.v8
    code:
      local:
        filename: /etc/arion/auth_filter.wasm

Disable on a route

There is no per-route WASM configuration, but any filter can be switched off for a route with a FilterConfig wrapper keyed by the filter's chain name:

typed_per_filter_config:
  envoy.filters.http.wasm:
    "@type": type.googleapis.com/envoy.config.route.v3.FilterConfig
    disabled: true

Instance lifecycle

The module is compiled once at configuration load. Instances are created lazily: the first request that needs one instantiates it and runs the plugin's on_plugin_start hook; when the transaction completes, the instance is reset and parked in a lock-free pool (up to 1024 per filter) for the next request. Each in-flight request holds its own instance, so plugin state is request-local unless you use shared state. Which hooks run is discovered from the module's exports: a plugin that only exports on_request_headers costs nothing on the response path.

Verify

With the SDK's dummy_filter example module loaded, an unauthenticated request is answered by the plugin itself:

curl -i http://127.0.0.1:8080/
HTTP/1.1 401 Unauthorized
...
401 Unauthorized: missing Authorization header

Limits

  • Body hooks fully buffer the request or response body before the plugin sees it; there is no streaming body API.
  • code must be a local data source. Remote code and the environment_variable source are rejected.
  • Envoy's fail_open, failure_policy, reload_config, capability_restriction_config, and VM environment_variables fields are not supported; a config using them refuses to start (see Envoy compatibility).
  • Per-route control is disable-only — no per-route plugin configuration.
  • A plugin runtime error fails the request with a 500; there is no fail-open mode.

Field-by-field details are in the wasm filter reference; to write the module itself, continue with the Rust SDK.

Continue

Start typing to search the site.

↑ ↓ to move Enter to open Esc to close