a7-plugin-ext-plugin

star 1

Skill for configuring the API7 Enterprise Edition external plugin system (ext-plugin-pre-req, ext-plugin-post-req, ext-plugin-post-resp) via the a7 CLI. Covers Plugin Runner architecture, configuration for Go/Java/Python runners, RPC protocol, graceful degradation, and performance considerations.

api7 By api7 schedule Updated 5/12/2026

name: a7-plugin-ext-plugin description: >- Skill for configuring the API7 Enterprise Edition external plugin system (ext-plugin-pre-req, ext-plugin-post-req, ext-plugin-post-resp) via the a7 CLI. Covers Plugin Runner architecture, configuration for Go/Java/Python runners, RPC protocol, graceful degradation, and performance considerations. version: "1.0.0" author: API7.ai Contributors license: Apache-2.0 metadata: category: plugin apisix_version: ">=3.0.0" plugin_name: ext-plugin-pre-req related_plugins: - ext-plugin-post-req - ext-plugin-post-resp a7_commands: - a7 route create - a7 route update - a7 config sync


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:

Plugin Phase Priority Description
ext-plugin-pre-req rewrite 12000 Before built-in Lua plugins
ext-plugin-post-req access −3000 After Lua plugins, before upstream
ext-plugin-post-resp before_proxy −4000 After 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:

Field Type Required Default Description
conf array No List of external plugins to execute
conf[].name string Yes Plugin identifier (1–128 chars)
conf[].value string Yes JSON string configuration passed to the plugin
allow_degradation boolean No false When 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

Language Repository Status
Go apache/apisix-go-plugin-runner GA
Java apache/apisix-java-plugin-runner GA
Python apache/apisix-python-plugin-runner Experimental
JavaScript zenozeng/apisix-javascript-plugin-runner Community

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

Feature ext-plugin-pre-req ext-plugin-post-req ext-plugin-post-resp
Phase rewrite access before_proxy
Runs Before Lua plugins After Lua plugins After 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

Symptom Cause Fix
failed to receive RPC_PREPARE_CONF Runner not listening or socket path mismatch Verify socket path in configuration matches API7_LISTEN_ADDRESS
503 Service Unavailable Runner crashed or not started Check runner logs; verify cmd path is correct
Runner not receiving env vars Nginx hides env vars by default Add vars to nginx_config.envs in gateway group configuration
Slow response times External plugin doing heavy work Profile runner; consider async processing
ext-plugin-post-resp conflicts Incompatible with proxy-* plugins Use ext-plugin-post-req instead, or remove proxy-mirror/cache
Install via CLI
npx skills add https://github.com/api7/a7 --skill a7-plugin-ext-plugin
Repository Details
star Stars 1
call_split Forks 0
navigation Branch main
article Path SKILL.md
More from Creator