Conditions

The matching language used by firewall, rate limiting, cache, and load balancer rules.

Conditions System

Conditions are the core matching mechanism used by Firewall, Rate Limiting, Cache, and Load Balancer plugins. A condition compares a resolved value from the request context against an expected value.

Structure

{
  "left": "<path>",
  "operator": "<operator>",
  "value": "<expected_value>",
  "next": "and"
}
FieldTypeDescription
leftstringPath to resolve from request context
operatorstringComparison operator
valueanyExpected value (string, number, bool, array)
nextstringLogical operator to next condition ("and" or "or", default "and")

Condition paths

Request fields

PathTypeDescription
req.host / http.hoststringRequest host header
req.path / http.pathstringRequest path (including query string)
req.method / http.methodstringHTTP method (GET, POST, etc.)
req.scheme / http.schemestringRequest scheme (http, https)
req.ip / http.ipstringResolved client IP
req.peer_ip / http.peer_ipstringDirect connection IP
req.user_agent / http.user_agentstringUser-Agent header

IP Intelligence fields

PathTypeDescription
ip.countrystringCountry code (ISO 3166-1 alpha-2)
ip.regionstringRegion/state code
ip.citystringCity name
ip.asnnumberASN number
ip.as_orgstringASN organization name
ip.providerstringHosting/cloud provider label (e.g. "Hostinger")
ip.is_vpnboolIP is a known VPN
ip.is_torboolIP is a Tor exit node
ip.is_datacenterboolIP is from a datacenter/hosting
ip.is_proxyboolIP is a known proxy
ip.is_mobileboolIP is from a mobile network
ip.is_residentialboolIP is residential
ip.is_residential_proxyboolIP is a residential proxy
ip.network_typestringNetwork type classification
ip.risk_scorenumberRisk score (0-100)

Headers and cookies

PathTypeDescription
req.header.<name>stringRequest header value
http.header.<name>stringRequest header value
req.query.<name>stringQuery parameter value
http.query.<name>stringQuery parameter value
req.cookie.<name>stringCookie value
http.cookie.<name>stringCookie value

JWT claim extraction

A header path ending in .jwt.<claim.path> decodes the header value as a JWT (a leading Bearer is stripped), then navigates the payload by dotted claim path:

PathMeaning
req.header.authorization.jwt.user_iduser_id claim of the Bearer token
req.header.authorization.jwt.data.rolenested claim data.role
header.token.jwt.user_idbare header. prefix also works (same for rate-limit keys)

Operators

OperatorDescriptionExample
equalsExact match"req.method" equals "POST"
not_equalsNot equal"ip.country" not equals "US"
containsString contains"req.path" contains "/api/"
not_containsString does not contain"req.path" not contains "/health"
starts_withString starts with"req.path" starts_with "/admin/"
ends_withString ends with"req.path" ends_with ".css"
existsValue exists (not null)"ip.is_vpn" exists
not_existsValue does not exist"ip.is_vpn" not_exists
inValue is in array"ip.country" in ["US", "CA", "GB"]
not_inValue is not in array"ip.country" not_in ["CN", "RU"]
greater_thanNumeric greater than"ip.risk_score" greater_than 30
greater_than_or_equalNumeric >="ip.risk_score" greater_than_or_equal 50
less_thanNumeric less than"ip.risk_score" less_than 10
less_than_or_equalNumeric <="ip.asn" less_than_or_equal 99999
regexRegular expression match"req.path" regex "^/api/v[0-9]+/"

Logical operators

Multiple conditions are combined with and (default) or or:

AND (default)

All conditions must match:

{
  "conditions": [
    { "left": "req.path", "operator": "starts_with", "value": "/api/" },
    { "left": "ip.country", "operator": "not_equals", "value": "US" }
  ]
}

OR

Any condition can match:

{
  "conditions": [
    { "left": "ip.is_tor", "operator": "equals", "value": true, "next": "or" },
    { "left": "ip.is_vpn", "operator": "equals", "value": true, "next": "or" },
    { "left": "ip.risk_score", "operator": "greater_than", "value": 30 }
  ]
}

This matches if the IP is a Tor exit or a VPN or has risk score > 30.

Mixed AND/OR

{
  "conditions": [
    { "left": "req.path", "operator": "starts_with", "value": "/api/", "next": "and" },
    { "left": "ip.is_tor", "operator": "equals", "value": true, "next": "or" },
    { "left": "ip.is_vpn", "operator": "equals", "value": true }
  ]
}

This matches if:

  • (path starts with /api/ AND is Tor) OR is VPN

Examples

Block Tor exits from specific paths

{
  "conditions": [
    { "left": "req.path", "operator": "starts_with", "value": "/admin/" },
    { "left": "ip.is_tor", "operator": "equals", "value": true }
  ]
}

Allow only specific countries

{
  "conditions": [
    { "left": "ip.country", "operator": "not_in", "value": ["US", "CA", "GB", "AU"] }
  ]
}

Block high-risk IPs on API endpoints

{
  "conditions": [
    { "left": "req.path", "operator": "starts_with", "value": "/api/" },
    { "left": "ip.risk_score", "operator": "greater_than", "value": 50 }
  ]
}

Rate limit by API key header

{
  "conditions": [
    { "left": "req.path", "operator": "starts_with", "value": "/api/" }
  ],
  "key": "req.header.X-API-Key"
}

Cache by country

{
  "conditions": [
    { "left": "req.path", "operator": "starts_with", "value": "/content/" }
  ],
  "cache_key": {
    "mode": "custom",
    "parts": ["ip.country"]
  }
}

Type coercion

When comparing values of different types:

  • String ↔ Number: The string is parsed as a float for comparison
  • String ↔ Bool: Direct comparison (no coercion)
  • Null ↔ Null: Equal
  • Any ↔ Null: Not equal (unless using exists/not_exists)
Copyright © 2026