init match & replace plugin

Signed-off-by: Hadi <112569860+anotherhadi@users.noreply.github.com>
This commit is contained in:
Hadi
2026-05-20 20:25:01 +02:00
parent a708830309
commit 6af1388652
+125
View File
@@ -0,0 +1,125 @@
Plugin = {
name = "Match & Replace",
description = [[
Automatically find and replace content in requests and responses.
**Config** (YAML):
```yaml
rules:
- on: "request" # "request", "response", or "both" (default: "both")
url: "example%.com" # optional: Lua pattern to filter by URL
target: "body" # "body", "path", "url", or "header:Name"
find: "old_string" # Lua pattern to search
replace: "new_string" # replacement string (supports %1, %2 for captures)
```
Example (inject a debug flag in JSON bodies):
```yaml
rules:
- on: "both"
url: "api%.example%.com"
target: "body"
find: '"debug":false'
replace: '"debug":true'
```
Example (replace an Authorization header):
```yaml
rules:
- on: "request"
target: "header:Authorization"
find: "Bearer .*"
replace: "Bearer MY_NEW_TOKEN"
```
Example (rewrite a path prefix):
```yaml
rules:
- on: "request"
url: "staging%.example%.com"
target: "path"
find: "^/v1/"
replace: "/v2/"
```
]],
priority = 50,
on_request = { sync = true },
on_response = { sync = true },
}
local rules = {}
function on_config()
rules = {}
local cfg = get_config()
if not cfg or not cfg.rules then
return
end
for _, r in ipairs(cfg.rules) do
if r.find and r.find ~= "" then
table.insert(rules, {
on = r.on or "both",
url = r.url,
target = r.target or "body",
find = r.find,
replace = r.replace or "",
})
end
end
end
local function should_apply(rule, req, context)
if rule.on ~= "both" and rule.on ~= context then
return false
end
if rule.url and not req.url:match(rule.url) then
return false
end
return true
end
local function apply(rule, req, res, context)
local target = rule.target
if target == "body" then
local obj = (context == "response") and res or req
local body = obj:get_body()
local new_body = body:gsub(rule.find, rule.replace)
if new_body ~= body then
obj:set_body(new_body)
end
elseif target == "path" then
local new_path = req.path:gsub(rule.find, rule.replace)
if new_path ~= req.path then
req:set_path(new_path)
end
elseif target == "url" then
local new_url = req.url:gsub(rule.find, rule.replace)
if new_url ~= req.url then
req:set_url(new_url)
end
elseif target:sub(1, 7) == "header:" then
local name = target:sub(8)
local obj = (context == "response") and res or req
local val = obj.headers[name] or ""
local new_val = val:gsub(rule.find, rule.replace)
if new_val ~= val then
obj:set_header(name, new_val)
end
end
end
function on_request(req)
for _, rule in ipairs(rules) do
if should_apply(rule, req, "request") then
apply(rule, req, nil, "request")
end
end
end
function on_response(req, res)
for _, rule in ipairs(rules) do
if should_apply(rule, req, "response") then
apply(rule, req, res, "response")
end
end
end