跳到主要内容
版本:3.10.x

API7 网关 AI Agent Skill:plugin serverless

本页提供 plugin serverless 场景的 API7 企业版操作指南。请保留下方命令、字段、配置项和 API 路径的原样,并根据实际网关环境替换示例值。

Overview

API7 Enterprise Edition (API7 EE) provides two serverless plugins that execute inline Lua functions during request processing:

  • serverless-pre-function — runs at the beginning of the specified phase (priority 10000, executes early).
  • serverless-post-function — runs at the end of the specified phase (priority −2000, executes late).

Both share identical configuration. Functions are defined as Lua strings in the Admin API and compiled at load time.

When to Use

  • Inject custom request/response logic without writing a full plugin.
  • Quick prototyping of header injection, redirects, or logging.
  • Add lightweight pre-processing (rewrite) or post-processing (log).
  • Dynamic routing decisions based on request attributes.

Plugin Configuration Reference

FieldTypeRequiredDefaultValid ValuesDescription
phasestringNo"access"rewrite, access, header_filter, body_filter, log, before_proxyPhase when functions execute
functionsarray[string]YesLua function stringsFunctions executed sequentially; each must return a function

Function Signature

Since API7 EE (based on APISIX v2.6+), functions receive two arguments:

return function(conf, ctx)
-- conf: plugin configuration object
-- ctx: API7 EE request context (shared across plugins)
--
-- Optional return:
-- return code, body -- exit immediately with HTTP status + body
-- return -- continue to next function / plugin
end

Rules:

  • The string MUST return a function. Raw statements are rejected.
  • Functions are cached via LRU cache; update the route to pick up changes.

Phase Execution Order

1. rewrite         → modify request before routing
2. access → authorization / authentication checks
3. before_proxy → last chance before upstream call
4. header_filter → modify response headers
5. body_filter → modify response body (chunked via ngx.arg)
6. log → logging after response sent (read-only)

Phase Restrictions

PhaseCan Read RequestCan Modify RequestCan Modify ResponseCan Exit
rewrite
access
before_proxy
header_filter✅ (headers)
body_filter✅ (body chunks)
log

Step-by-Step Examples

1. Basic Logging

a7 route create --gateway-group default -f - <<'EOF'
{
"id": "serverless-log",
"uri": "/api/*",
"plugins": {
"serverless-pre-function": {
"phase": "rewrite",
"functions": [
"return function() ngx.log(ngx.WARN, 'incoming request: ', ngx.var.uri) end"
]
}
},
"upstream": {
"type": "roundrobin",
"nodes": [{"host": "backend", "port": 8080, "weight": 1}]
}
}
EOF

2. HTTP to HTTPS Redirect

a7 route create --gateway-group default -f - <<'EOF'
{
"id": "force-https",
"uri": "/*",
"plugins": {
"serverless-pre-function": {
"phase": "rewrite",
"functions": [
"return function() if ngx.var.scheme == 'http' then ngx.header['Location'] = 'https://' .. ngx.var.host .. ngx.var.request_uri; ngx.exit(301) end end"
]
}
},
"upstream": {
"type": "roundrobin",
"nodes": [{"host": "backend", "port": 8080, "weight": 1}]
}
}
EOF

3. Request Header Injection

a7 route create --gateway-group default -f - <<'EOF'
{
"id": "inject-headers",
"uri": "/api/*",
"plugins": {
"serverless-pre-function": {
"phase": "rewrite",
"functions": [
"return function(conf, ctx) ngx.req.set_header('X-Request-ID', ngx.var.request_id); ngx.req.set_header('X-Real-IP', ngx.var.remote_addr) end"
]
}
},
"upstream": {
"type": "roundrobin",
"nodes": [{"host": "backend", "port": 8080, "weight": 1}]
}
}
EOF

4. Modify Upstream URI

a7 route create --gateway-group default -f - <<'EOF'
{
"id": "rewrite-uri",
"uri": "/legacy/*",
"plugins": {
"serverless-post-function": {
"phase": "access",
"functions": [
"return function(conf, ctx) ctx.var.upstream_uri = '/v2' .. ngx.var.uri end"
]
}
},
"upstream": {
"type": "roundrobin",
"nodes": [{"host": "backend", "port": 8080, "weight": 1}]
}
}
EOF

5. Response Header Modification (header_filter phase)

a7 route create --gateway-group default -f - <<'EOF'
{
"id": "resp-headers",
"uri": "/api/*",
"plugins": {
"serverless-post-function": {
"phase": "header_filter",
"functions": [
"return function() ngx.header['X-Processed-By'] = 'API7-EE'; ngx.header['X-Response-Time'] = ngx.now() - ngx.req.start_time() end"
]
}
},
"upstream": {
"type": "roundrobin",
"nodes": [{"host": "backend", "port": 8080, "weight": 1}]
}
}
EOF

6. Closure with Persistent State

a7 route create --gateway-group default -f - <<'EOF'
{
"id": "closure-counter",
"uri": "/count",
"plugins": {
"serverless-pre-function": {
"phase": "log",
"functions": [
"local count = 0; return function() count = count + 1; ngx.log(ngx.WARN, 'request count: ', count) end"
]
}
},
"upstream": {
"type": "roundrobin",
"nodes": [{"host": "backend", "port": 8080, "weight": 1}]
}
}
EOF

7. Multiple Sequential Functions

a7 route create --gateway-group default -f - <<'EOF'
{
"id": "multi-fn",
"uri": "/api/*",
"plugins": {
"serverless-pre-function": {
"phase": "rewrite",
"functions": [
"return function() ngx.log(ngx.WARN, 'step one') end",
"return function() ngx.log(ngx.WARN, 'step two') end"
]
}
},
"upstream": {
"type": "roundrobin",
"nodes": [{"host": "backend", "port": 8080, "weight": 1}]
}
}
EOF

8. Custom Authentication Guard

a7 route create --gateway-group default -f - <<'EOF'
{
"id": "custom-auth",
"uri": "/admin/*",
"plugins": {
"serverless-pre-function": {
"phase": "access",
"functions": [
"return function() local token = ngx.var.http_authorization; if not token or token ~= 'Bearer secret123' then return 401, '{\"error\":\"unauthorized\"}' end end"
]
}
},
"upstream": {
"type": "roundrobin",
"nodes": [{"host": "backend", "port": 8080, "weight": 1}]
}
}
EOF

Available Lua APIs

Core ngx APIs

-- Request
ngx.var.uri, ngx.var.request_uri, ngx.var.scheme, ngx.var.host
ngx.var.remote_addr, ngx.var.request_method, ngx.var.request_id
ngx.req.get_headers(), ngx.req.get_uri_args(), ngx.req.get_method()
ngx.req.set_header(name, value), ngx.req.read_body(), ngx.req.get_body_data()

-- Response
ngx.header["Name"] = "value"
ngx.status = 200
ngx.say(data), ngx.print(data)
ngx.exit(status), ngx.redirect(uri, status)

-- Logging
ngx.log(ngx.ERR, msg), ngx.log(ngx.WARN, msg), ngx.log(ngx.INFO, msg)

-- Utilities
ngx.time(), ngx.now(), ngx.encode_base64(str), ngx.decode_base64(str)

API7 EE Context Variables

ctx.var.upstream_uri = "/new/path"   -- modify upstream request URI
ctx.curr_req_matched._path -- matched route path
ctx.consumer_name -- authenticated consumer name
ctx.route_id -- current route ID
ctx.service_id -- current service ID

Available Libraries

local json = require("cjson")
local core = require("apisix.core")
local http = require("resty.http")
local lrucache = require("resty.lrucache")

Config Sync Example

version: "1"
gateway_group: default
routes:
- id: serverless-demo
uri: /api/*
plugins:
serverless-pre-function:
phase: rewrite
functions:
- "return function() ngx.req.set_header('X-Gateway', 'api7-ee') end"
serverless-post-function:
phase: log
functions:
- "return function() ngx.log(ngx.WARN, 'request completed') end"
upstream:
type: roundrobin
nodes:
- host: backend
port: 8080
weight: 1

Key Differences: Pre vs Post

Featureserverless-pre-functionserverless-post-function
ExecutionBeginning of phaseEnd of phase
Priority10000 (high — runs early)−2000 (low — runs late)
Typical UsePre-processing, auth guardsPost-processing, logging

Troubleshooting

SymptomCauseFix
only accept Lua function, the input code type is nilFunction string doesn't return a functionWrap code in return function() ... end
failed to compile functionSyntax error in Lua codeTest code in a Lua REPL first
Function changes not taking effectLRU cache holds old compiled functionUpdate route to trigger recompilation
ngx.say not working in header_filterPhase restriction — cannot write body in header_filterUse header_filter only for ngx.header modifications
No output in log phaseLog phase is read-onlyUse ngx.log() instead of ngx.say()
Blocking I/O causes timeoutSynchronous operations in request pathUse ngx.timer.at() for async work

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