Plugins
Every node in a featherbit policy graph is a plugin. A single factory — create_plugin() in src/plugins/mod.rs — maps each node's type string from the YAML config to a plugin instance. The plugin system is two-tier:
- Native plugins — node types implemented in Rust and compiled into the binary. Two of them,
listenerandclient, are structural: they mark the entry and exit of every graph, take no configuration, and are documented together on their own page. - Scripted plugins — the
scriptnode runs custom plugin logic written in Lua (Luau runtime), loaded from a file or inline.
Every plugin implements the same contract: async fn execute(ctx, named_inputs) -> Result<PluginOutput, PluginExecutionError>. On success, the (possibly mutated) Context flows out of the node's success port; on failure, the error carries the Context so the graph engine can route it through the node's error port instead. Invalid node configuration is rejected by the plugin's from_config at config load time, never at request time.
featherbit expresses the classic proxy phase model (rewrite/access/header_filter/body_filter) as explicit graph position: a "request-phase" plugin is a node wired before upstream; a "response-phase" plugin comes after it. Where a plugin supports a subset of a config schema, its page carries a note describing the exact behavior.
Structural & core proxy
| Type | Description |
|---|---|
listener / client | Fixed graph entry and exit nodes (no config) |
upstream | Forward to a backend pool with round-robin, least-connections, or IP-hash balancing |
proxy-rewrite | Rewrite request path and headers |
response-rewrite | Rewrite response status, headers, and body (regex filters, encoding-aware) |
body-transformer | Rewrite request/response JSON bodies via templates |
degraphql | Expose a REST endpoint backed by a GraphQL upstream |
redirect | HTTP redirect, or force HTTP→HTTPS |
echo | Wrap or replace the response body (demo/testing) |
gzip / brotli | Compress the response body when the client accepts it |
request-id | Attach a unique request-id header |
real-ip | Recover the client IP from a trusted proxy header |
Error handling & mocking
| Type | Description |
|---|---|
error-handler | Render custom error responses with template variables |
error-page | Replace 404/500/502/503 bodies with configured pages |
exit-transformer | Remap status and rewrite the body of gateway-generated exits |
mocking | Respond with a configured mock instead of proxying (terminal node) |
Security & access control
| Type | Description |
|---|---|
cors | CORS preflight and response header management |
csrf | Double-submit CSRF token validation |
ip-restriction | Allow/deny by IP or CIDR |
ua-restriction | Allow/deny by User-Agent regex |
referer-restriction | Allow/deny by Referer host |
uri-blocker | Block requests matching URI regex rules |
request-size-limit | Reject over-sized request bodies |
request-validation | Validate headers/body against JSON Schema |
data-mask | Mask or remove sensitive fields in bodies, headers, query |
Traffic control
Several traffic plugins need to act both before and after the upstream call. featherbit expresses this as a pair of nodes wired around upstream, both configured with the same id (or key) and sharing process-wide state — the same request/response split proxy-rewrite uses. Each such page documents the pairing.
| Type | Description |
|---|---|
rate-limit | Token-bucket rate limiting per IP or header key |
limit-count | Fixed-window request-count limiting (shared counters) |
limit-conn | Concurrent-request limiting (acquire/release node pair) |
api-breaker | Circuit breaker on unhealthy upstreams (check/observe pair) |
traffic-split | Weighted / conditional traffic steering (canary, blue-green) |
proxy-mirror | Fire-and-forget clone of requests to a shadow upstream |
proxy-cache | Cache upstream responses (lookup/store node pair) |
fault-injection | Inject delays and abort responses (percentage + vars gated) |
workflow | Ordered rules — reject or rate-limit the first matching case |
traffic-label | Tag matching requests with headers and context labels |
Serverless & FaaS
The FaaS plugins invoke an external function and return its reply as the gateway response — they replace the upstream, so wire their success edge to client.in. The serverless functions run inline Lua at a graph position (before or after the upstream) via the same runtime as the script node.
| Type | Description |
|---|---|
serverless-pre-function | Run inline Lua before the upstream |
serverless-post-function | Run inline Lua after the upstream |
oas-validator | Validate requests against an inline OpenAPI 3 spec |
aws-lambda | Invoke an AWS Lambda (SigV4 or API-key auth) |
azure-functions | Invoke an Azure Function |
openwhisk | Invoke an Apache OpenWhisk action |
openfunction | Invoke an OpenFunction function |
Observability & logging
Logger plugins ship access logs to an external sink. They are fire-and-forget: a logger node builds a JSON entry from the request, hands it to a shared batch queue (BatchSink), and returns immediately — the request path never blocks on log I/O. Place a logger after upstream (so status and body are populated); wire it on error paths too if you want failures logged. All loggers share the batch keys (batch_max_size, inactive_timeout, buffer_duration, max_retry_count, retry_delay) and an optional log_format map of name → "$var" templates.
| Type | Description |
|---|---|
logging | Structured JSON access logging to stdout |
http-logger | Ship logs to an HTTP endpoint |
tcp-logger / udp-logger | Ship logs over a raw TCP / UDP socket |
syslog | Ship logs via syslog (RFC 5424) over TCP or UDP |
file-logger | Append logs to a local file |
error-log-logger | Ship request-level errors to a TCP sink |
elasticsearch-logger | Bulk-index logs into Elasticsearch |
clickhouse-logger | Insert logs into ClickHouse |
loki-logger | Push logs to Grafana Loki |
splunk-hec-logging | Ship logs to Splunk HEC |
datadog | Emit DogStatsD metrics to the Datadog agent |
loggly | Ship logs to SolarWinds Loggly |
google-cloud-logging | Ship logs to Google Cloud Logging |
sls-logger | Ship logs to Alibaba Cloud SLS |
tencent-cloud-cls | Ship logs to Tencent Cloud CLS |
skywalking-logger | Ship logs to Apache SkyWalking |
lago | Meter requests as Lago billing events |
Tracing & metrics
featherbit exposes built-in Prometheus metrics (per-route request counts and latency, per-node execution metrics) at the admin /metrics endpoint — always on, no plugin required (see Observability). The plugins here add distributed tracing and extra metric dimensions.
The three tracers are start/end node pairs: a start node (placed after the listener) extracts or creates the trace context, propagates it to the upstream, and stores the span; an end node (after the upstream) exports the finished span to the collector, fire-and-forget. The span is carried per-request, so the pair needs no shared id.
| Type | Description |
|---|---|
prometheus | Adds a per-consumer request counter to the built-in metrics |
opentelemetry | OTLP/HTTP trace export with W3C traceparent propagation |
zipkin | Zipkin v2 trace export with B3 propagation |
skywalking | SkyWalking segment export with sw8 propagation |
Authentication & consumers
featherbit models API clients as consumers — named identities with per-auth-plugin credentials, declared under consumers: in gateway.yaml and managed via /api/consumers. Auth plugins with use_consumers: true resolve the presented credential to a consumer and attach its identity (consumer.* keys in context.message, X-Consumer-* headers); the restriction plugins then act on it.
| Type | Description |
|---|---|
key-auth | API-key auth via header or query; consumer-aware |
basic-auth | HTTP Basic authentication; consumer-aware |
jwt-auth | HMAC JWT validation, inline or per-consumer secrets |
hmac-auth | HMAC request signing (access-key/secret-key), consumer-aware |
jwe-decrypt | Decrypt a JWE token (dir + A256GCM) into a forwarded header |
multi-auth | Chain auth plugins — accept the first that succeeds |
ldap-auth | Authenticate HTTP Basic credentials against an LDAP server |
consumer-restriction | Allow/deny by consumer name or group |
acl | Allow/deny by consumer group |
attach-consumer-label | Copy consumer labels into upstream request headers |
External auth & authorization
These plugins delegate the auth or authorization decision to an external service over HTTP (via the shared outbound client). The SSO plugins support interactive browser login as well as stateless token validation: featherbit has no server-side session store, but the interactive flows keep all state in an encrypted client-side cookie (see the cookie-session codec), so they work across a horizontally-scaled deployment as long as instances share the session secret. Each page's Deviations section states the exact behavior and the one remaining limitation (no server-side revocation before cookie expiry).
| Type | Description |
|---|---|
forward-auth | Delegate the decision to an external HTTP auth service |
opa | Delegate authorization to an Open Policy Agent instance |
authz-casbin | Embedded Casbin RBAC/ABAC enforcement (no network) |
authz-keycloak | Keycloak UMA permission check |
authz-casdoor | Casdoor: bearer-token introspection or interactive OAuth login |
openid-connect | OIDC: bearer-token validation or interactive Authorization Code login |
cas-auth | CAS: ticket validation or interactive SSO login |
wolf-rbac | Wolf RBAC token check |
dingtalk-auth | DingTalk code/token validation |
feishu-auth | Feishu/Lark code/token validation |
Scripting
| Type | Description |
|---|---|
script | Custom plugin logic written in Lua (Luau), from a file or inline |
Reading the reference pages
Each plugin page documents:
- Configuration — the keys the plugin's
from_configaccepts, with types, defaults, and which malformed shapes are rejected at config load. - Behavior — what the plugin reads and writes on the Context (
request,response,message,errors), when it takes thesuccessversuserrorport, and the error codes it can emit.
Unknown type strings fail policy compilation with Unknown plugin type: <name>.