Rule API Reference

The rule engine is the core traffic control mechanism in RelayCore. Each rule consists of a Filter (what to match), Action (what to do), and Stage (when to execute), executed by priority in the proxy pipeline.

Rule Structure

{
  "id": "rule-001",           // Unique identifier
  "name": "Block Tracking",   // Human-readable name
  "active": true,             // Whether enabled
  "stage": "RequestHeaders",  // Execution stage
  "priority": 100,            // Priority (higher = earlier, default 0)
  "termination": "Continue",  // How to handle subsequent rules
  "filter": { ... },          // Match condition
  "actions": [ ... ],         // Action list (ordered)
  "constraints": {            // Performance limits (optional)
    "timeout_ms": 5000
  }
}

Execution Stages

The stage determines when a rule is evaluated. Rules within the same stage execute by priority descending:

StageLayerTriggerAvailable Filters
ConnectL3/L4TCP connection establishedIP/Port/Protocol/TransparentMode
RequestHeadersL7After request headers parsedUrl/Host/Path/Method/RequestHeader
RequestBodyL7Request body readyAbove + body content
ResponseHeadersL7Response headers receivedStatusCode/ResponseHeader
ResponseBodyL7Response body readyAbove + ResponseBody
WebSocketMessageL7Each WS frame receivedWebSocketMessage

Filters

Filters determine whether a rule applies. Available by stage:

Global

FilterDescriptionExample
AllMatches all traffic{"type": "All"}

L3/L4 (Connect stage)

SrcIpSource IP (CIDR)"192.168.1.0/24"
DstPortDestination port443
ProtocolTransport protocol"TCP"
TransparentModeWhether transparent proxytrue

L7 (HTTP/WS stages)

UrlFull URL match
HostDomain match
PathURL path match
MethodHTTP method
RequestHeaderRequest header (name + optional value)
ResponseHeaderResponse header (name + optional value)
StatusCodeResponse status code
ResponseBodyResponse body content
WebSocketMessageWebSocket message content

Logical Compositors

AndAll child filters must match
OrAny child filter matches (1.0 uses any() semantics)
NotNegate the child filter

StringMatcher

Most L7 filters accept a StringMatcher mode:

ModeDescriptionExample
ExactExact match
ContainsSubstring match
PrefixStarts with
SuffixEnds with
RegexRegular expression
GlobGlob/wildcard pattern

Actions

Actions define what to do when a rule matches. A rule can have multiple actions, executed in order.

Universal Control

DropDrop connection immediately
AbortRST reset connection
Delay {"ms":100}Latency simulation
Throttle {"kbps":1024}Bandwidth throttle
InspectPause flow for manual inspection (requires Tauri UI; no-op in CLI mode)
TagTag the flow (visible to scripts)
SetVariableSet a cross-rule variable
RateLimitRate limit by key

L3/L4 Network

RedirectIpRedirect target IP
ForwardPortChange target port
SetTtlSet IP TTL

L7 HTTP — Terminal (stops proxying)

MockResponseReturn mock HTTP response
MapLocalServe local file as response
MapRemoteForward to different backend
RedirectHTTP redirect

L7 HTTP — Modifications

AddRequestHeader / UpdateRequestHeader / DeleteRequestHeader
AddResponseHeader / UpdateResponseHeader / DeleteResponseHeader
SetRequestMethod / SetRequestUrl
SetRequestBody / SetResponseBody
SetResponseStatus

L7 HTTP — Transformations

TransformRequestBody / TransformResponseBody

WebSocket

MockWebSocketMessageReplace WS message
DropWebSocketMessageDrop WS message

BodySource

For actions that need body content (SetRequestBody, SetResponseBody, MockResponse, MapLocal):

{"type": "Text",   "value": "{\"status\":\"ok\"}"}
{"type": "File",   "value": "/path/to/mock.json"}
{"type": "Base64", "value": "eyJzdGF0dXMiOiJvayJ9"}

BodyTransform

// Regex replace
{"type": "RegexReplace", "config": {"pattern": "http://", "replacement": "https://"}}
// JsonPath set
{"type": "JsonPathSet", "config": {"path": "$.data.secret", "value": "***"}}
// JsonPath delete
{"type": "JsonPathDelete", "config": {"path": "$.debug"}}

Mustache Variable Substitution

String fields in actions support Mustache template syntax, resolved at runtime:

VariableResolves to
{{host}}Request target hostname
{{request.path}}Request URL path
{{request.url}}Full request URL
{{request.method}}HTTP method
{{ip}} / {{client_ip}}Client IP address
{{previous}}The field's original value before this action
{{variable.xxx}}Value set by SetVariable action
{{timestamp}}Unix millisecond timestamp

Termination

ContinueKeep processing subsequent rules (default)
StopSkip remaining rules in this stage

RateLimit

{
  "type": "RateLimit",
  "config": {
    "key": "{{ip}}:{{request.path}}",
    "limit": 100,
    "window_ms": 60000
  }
}

WebSocket Direction

{"type": "MockWebSocketMessage", "config": {
  "direction": "Incoming",     // or "Outgoing"
  "message": "replaced message"
}}

Managing Rules

# HTTP API
curl -X PUT http://127.0.0.1:8082/api/v1/rules \
  -H "Content-Type: application/json" \
  -d '{"id":"r1","name":"log-api","active":true,"stage":"RequestHeaders",
       "priority":10,"termination":"Continue",
       "filter":{"type":"Url","config":{"mode":"Contains","value":"/api/"}},
       "actions":[{"type":"AddRequestHeader","config":{"name":"X-Logged","value":"true"}}]}'

# MCP tool
mcp: relay-core set_rule --rule rule.json