Skip to main content
Version: 3.10.x

a7-plugin-ext-plugin

Overview

The API7 Enterprise Edition (API7 EE) external plugin system lets you run plugins written in Go, Java, Python, or JavaScript via a Plugin Runner process. API7 EE communicates with the runner over a Unix socket using FlatBuffers serialization.

Three plugins control when external plugins execute:

PluginPhasePriorityDescription
ext-plugin-pre-reqrewrite12000Before built-in Lua plugins
ext-plugin-post-reqaccess−3000After Lua plugins, before upstream
ext-plugin-post-respbefore_proxy−4000After upstream response received

When to Use

  • Implement custom logic in Go, Java, or Python instead of Lua.
  • Reuse existing business logic from non-Lua codebases.
  • Apply pre-processing (auth, validation) or post-processing (response transform).
  • Teams that prefer statically-typed languages over Lua.

Plugin Configuration Reference

All three plugins share the same schema:

FieldTypeRequiredDefaultDescription
confarrayNoList of external plugins to execute
conf[].namestringYesPlugin identifier (1–128 chars)
conf[].valuestringYesJSON string configuration passed to the plugin
allow_degradationbooleanNofalseWhen true, requests continue if runner is unavailable

Plugin Runner Architecture

┌─────────────┐ Unix Socket ┌───────────────┐
│ API7 EE │ ◄──────────────► │ Plugin Runner │
│ (Data Plane)│ FlatBuffers │ (Go/Java/Py) │
└─────────────┘ └───────────────┘
  1. API7 EE starts the runner as a subprocess (managed lifecycle).
  2. On ext-plugin-* trigger, API7 EE sends an RPC over Unix socket.
  3. Runner executes external plugins and returns the result.
  4. API7 EE applies modifications (headers, body, status) to the request/response.

RPC Protocol

  • PrepareConf: Syncs plugin configuration → returns a conf token (cached).
  • HTTPReqCall: Per-request execution with serialized HTTP data + conf token.
  • ExtraInfo: Runner can request additional data (variables, body, response).

Supported Plugin Runners

LanguageRepositoryStatus
Goapache/apisix-go-plugin-runnerGA
Javaapache/apisix-java-plugin-runnerGA
Pythonapache/apisix-python-plugin-runnerExperimental
JavaScriptzenozeng/apisix-javascript-plugin-runnerCommunity

API7 EE Configuration

Production Setup

API7 EE manages the runner as a subprocess. This is configured in the gateway group's configuration (via Dashboard or CLI sync).

ext-plugin:
cmd: ["/path/to/runner-executable", "run"]

Runner-Specific Commands

# Go runner
ext-plugin:
cmd: ["/opt/api7-go-runner", "run"]

# Java runner
ext-plugin:
cmd: ["java", "-jar", "-Xmx1g", "-Xms1g", "/opt/api7-runner.jar"]

# Python runner
ext-plugin:
cmd: ["python3", "/opt/api7-python-runner/apisix/main.py", "start"]

Development Setup (Standalone Runner)

For local development, run the runner separately:

# API7 EE configuration — do NOT set cmd
ext-plugin:
path_for_test: "/tmp/runner.sock"
# Start runner manually
API7_LISTEN_ADDRESS=unix:/tmp/runner.sock ./runner run

Environment Variables

Pass environment variables to the runner:

nginx_config:
envs:
- MY_ENV_VAR
- DATABASE_URL

Step-by-Step Examples

1. Single External Plugin

a7 route create --gateway-group default -f - <<'EOF'
{
"id": "ext-auth",
"uri": "/api/*",
"plugins": {
"ext-plugin-pre-req": {
"conf": [
{"name": "AuthFilter", "value": "{\"token_required\":true}"}
]
}
},
"upstream": {
"type": "roundrobin",
"nodes": [{"host": "backend", "port": 8080, "weight": 1}]
}
}
EOF

2. Multiple External Plugins with Degradation

a7 route create --gateway-group default -f - <<'EOF'
{
"id": "ext-chain",
"uri": "/api/*",
"plugins": {
"ext-plugin-pre-req": {
"conf": [
{"name": "AuthFilter", "value": "{\"token_required\":true}"},
{"name": "RateLimiter", "value": "{\"requests_per_second\":100}"}
],
"allow_degradation": true
}
},
"upstream": {
"type": "roundrobin",
"nodes": [{"host": "backend", "port": 8080, "weight": 1}]
}
}
EOF

3. All Three Plugin Types (Full Request Lifecycle)

a7 route create --gateway-group default -f - <<'EOF'
{
"id": "full-ext",
"uri": "/api/*",
"plugins": {
"ext-plugin-pre-req": {
"conf": [{"name": "auth-check", "value": "{}"}]
},
"ext-plugin-post-req": {
"conf": [{"name": "request-transform", "value": "{}"}]
},
"ext-plugin-post-resp": {
"conf": [{"name": "response-logger", "value": "{}"}]
}
},
"upstream": {
"type": "roundrobin",
"nodes": [{"host": "backend", "port": 8080, "weight": 1}]
}
}
EOF

Execution order: pre-req → (Lua plugins) → post-req → (upstream) → post-resp.

Config Sync Example

version: "1"
gateway_group: default
routes:
- id: ext-plugin-demo
uri: /api/*
plugins:
ext-plugin-pre-req:
conf:
- name: AuthFilter
value: '{"token_required":true}'
allow_degradation: true
upstream:
type: roundrobin
nodes:
- host: backend
port: 8080
weight: 1

Compatibility Matrix

Featureext-plugin-pre-reqext-plugin-post-reqext-plugin-post-resp
Phaserewriteaccessbefore_proxy
RunsBefore Lua pluginsAfter Lua pluginsAfter upstream response
proxy-mirror
proxy-cache
proxy-control
mTLS to upstream

ext-plugin-post-resp limitation: Uses internal transport mechanism, which makes it incompatible with proxy-mirror, proxy-cache, proxy-control, and mTLS to upstream.

Performance Considerations

  • Unix socket + FlatBuffers: Low-latency IPC, no TCP overhead.
  • Conf token caching: PrepareConf called once per config change, not per request.
  • Process management: API7 EE sends SIGTERM then SIGKILL (1s grace) on reload.
  • Degradation mode: Enable allow_degradation: true for non-critical plugins.
  • Connection reuse: Runner should reuse socket connections.

Troubleshooting

SymptomCauseFix
failed to receive RPC_PREPARE_CONFRunner not listening or socket path mismatchVerify socket path in configuration matches API7_LISTEN_ADDRESS
503 Service UnavailableRunner crashed or not startedCheck runner logs; verify cmd path is correct
Runner not receiving env varsNginx hides env vars by defaultAdd vars to nginx_config.envs in gateway group configuration
Slow response timesExternal plugin doing heavy workProfile runner; consider async processing
ext-plugin-post-resp conflictsIncompatible with proxy-* pluginsUse ext-plugin-post-req instead, or remove proxy-mirror/cache

This page is generated from a7-plugin-ext-plugin/SKILL.md in the api7/a7 repository. Browse all skills on the AI Agent Skills page.