Operate

HTTP plugins

Plugins are named HTTP filters. Declare them once, then reference their names in route order.

Declare and attach

server:
  plugin_dir: /etc/omlb/plugins

plugins:
  - name: request-id
    type: native
    id: request_id
    config: { header: x-request-id, force: true }

  - name: edge-header
    type: native
    id: header_inject
    config:
      response_set: { x-edge: omlb }

  - name: jwt-filter
    type: wasm
    path: jwt-filter.wasm
    isolation: per_request
    enabled: true
    config: { issuer: "https://issuer.example.com" }

routes:
  - name: api
    match: { host: api.example.com }
    upstream: api
    plugins: [request-id, edge-header, jwt-filter]

Every plugin has a unique name, type, and opaque JSON config. Native plugins use a compiled-in id; WASM plugins use a path, resolved under server.plugin_dir when relative. Routes apply listed filters in order. An unknown plugin name or duplicate plugin name is a validation error.

Native and WASM execution

Built-in native filter IDs include header_inject, request_id, rate_limit, basic_auth, ip_acl, and cors. Native code runs without a WASM sandbox, so treat its config as production code configuration.

WASM defaults to isolation: per_request, creating a fresh sandbox for each call. pooled reuses warm instances and may preserve guest state between requests; use it only for stateless, trusted filters that have been tested under concurrency.

Load and unload at runtime

# List the active registry
curl http://127.0.0.1:9090/plugins

# Load or replace one plugin until the next file reload.
curl -X POST http://127.0.0.1:9090/plugins \
  -H 'content-type: application/json' \
  --data '{"name":"edge-header","type":"native","id":"header_inject","config":{"response_set":{"x-edge":"omlb"}}}'

# Remove a runtime-loaded plugin.
curl -X DELETE http://127.0.0.1:9090/plugins/edge-header

The admin API can load or replace a plugin and unload one by name. Those API changes are ephemeral: the next file reload recreates the registry from YAML. Make durable changes in the configuration file, validate them, and remember that declared plugins and route chains are hot-reloadable while the server’s plugin directory is not.

Deployment practice

Build and version WASM artifacts separately, deploy them before the YAML that references them, run --check on the host, then exercise the affected route. Keep untrusted WASM at per_request, minimize plugin configuration secrets, and have a tested rollback file available.