Skip to main content
Match expressions define which requests a policy applies to. A policy carries a list of MatchExpr entries. All entries must match for the policy to execute (AND semantics). An empty list matches all requests.

AND vs OR

Within a single policy, match expressions are combined with AND. A policy with a path match and a method match only runs when both conditions are true. There is no built-in OR operator. To express OR, create multiple policies with the same config and different match lists. For example, to apply different rate limits to different parts of an API:
{
  "policies": [
    {
      "match": [
        { "path": { "path": { "prefix": "/v1/search" } } }
      ],
      "ratelimit": { "limit": 10, "window_ms": 60000 }
    },
    {
      "match": [
        { "path": { "path": { "prefix": "/v1/keys" } } }
      ],
      "ratelimit": { "limit": 1000, "window_ms": 60000 }
    }
  ]
}
Each policy is evaluated independently in order. A request to /v1/search matches policy 1 and gets the stricter limit. A request to /v1/keys skips policy 1 (path does not match) and hits policy 2. This approach is simpler to reason about than a recursive expression tree and covers the vast majority of routing needs. The proto schema is designed so that combinators (And/Or/Not) can be added later as new oneof branches without breaking the wire format.

Matcher types

Path

Matches against request.URL.Path using a string match. The path is compared without the query string. Patterns must include the leading slash.
ComparisonBehavior
ExactCase-sensitive by default. Set ignore_case to match case-insensitively.
PrefixCase-sensitive by default. Set ignore_case to match case-insensitively.
RegexUses Go’s RE2 engine. Patterns are compiled once and cached. Set ignore_case to wrap the pattern with (?i).
{
  "policies": [
    {
      "match": [
        { "path": { "path": { "prefix": "/v1/" } } }
      ]
      // ...omitted
    }
  ]
}

Method

Matches against the HTTP method. Comparison is always case-insensitive per the HTTP specification. Multiple methods can be listed, and the request matches if it uses any of them (OR semantics). An empty method list matches all methods.
{
  "policies": [
    {
      "match": [
        { "method": { "methods": ["POST", "PUT", "DELETE"] } }
      ]
      // ...omitted
    }
  ]
}
Matches against request headers. Header names are matched case-insensitively per HTTP specification. When a header has multiple values, the match succeeds if any value matches (OR semantics).
name
string
Header name. Matched case-insensitively.
match
oneof
Either present (bool, checks header existence) or value (string match against header values).
{
  "policies": [
    {
      "match": [
        { "header": { "name": "Authorization", "present": true } }
      ]
      // ...omitted
    }
  ]
}

Query parameter

Matches against URL query parameters. Parameter names are matched case-sensitively. When a parameter has multiple values, the match succeeds if any value matches (OR semantics).
name
string
Parameter name. Matched case-sensitively.
match
oneof
Either present (bool, checks parameter existence) or value (string match against parameter values).
{
  "policies": [
    {
      "match": [
        { "query_param": { "name": "debug", "present": true } }
      ]
      // ...omitted
    }
  ]
}

String match types

All string comparisons support three modes:
ModeBehavior
exactFull string equality. Supports ignore_case.
prefixMatches if the string starts with the given prefix. Supports ignore_case.
regexRegular expression match using Go’s RE2 syntax. Supports ignore_case (prepends (?i)).

Regex caching

Compiled regular expressions are cached in a thread-safe map keyed by the pattern string. The first evaluation of a regex pattern compiles and caches it. Subsequent evaluations reuse the compiled pattern.