Skip to content

匹配器

**匹配器**是一种路由DSL(领域特定语言),根据请求的属性(主机名、路径、方法、请求头、客户端IP等)来过滤请求。匹配器在GOST的多个地方使用,用于按条件路由流量:

组件 字段 作用范围
节点 matcher.rule 在跳跃点内选择节点
跳跃点组 hopGroup.hops[].matcher 在转发器内选择跳跃点条目
转发链组 chainGroup.chains[].matcher 在监听器/处理器内选择转发链条目

匹配器在所有三个位置使用相同的DSL和相同的路由上下文。可用的上下文字段取决于协议层:

层级 可用字段
节点(跳跃点内) HostPathMethodHeaderQueryBodyRegexpBodyJSONClientIPNetworkProto
跳跃点组(转发器) 与节点相同 — 通过 hop.SelectOptions 传递完整的HTTP请求上下文
转发链组 Host — 请求的目标主机名。RouteOptions 当前仅携带 Host

DSL参考

布尔运算符

规则支持标准布尔逻辑:

运算符 含义 示例
&& Host("a.com") && PathPrefix("/api/")
\|\| Host("a.com") \|\| Host("b.com")
! !Host("blocked.com")
() 分组 (Host("a.com") \|\| Host("b.com")) && PathPrefix("/api/")

匹配函数

函数 参数 说明 示例
Host pattern 精确或通配符匹配主机名(TLS时也匹配SNI) Host("*.example.com")
HostRegexp regex Go正则匹配主机名 HostRegexp("^api[0-9]+\\.example\\.com$")
Path pattern 精确匹配请求路径 Path("/api/v1/users")
PathPrefix prefix 匹配路径前缀 PathPrefix("/api/")
PathRegexp regex Go正则匹配路径 PathRegexp("\\.(jpeg\\|jpg\\|png)$")
Method method 匹配HTTP方法 Method("POST")
Header key 匹配请求头 key 是否存在 Header("Content-Type")
Header key, value 精确匹配请求头 key 的值 Header("Content-Type", "application/json")
Header key, op, value 比较运算符对比请求头 key 的数值 1 Header("Content-Length", "gt", "1024")
HeaderRegexp key, regex Go正则匹配请求头 key 的值 HeaderRegexp("Content-Type", "^application/(json\\|yaml)$")
Query key 匹配查询参数 key 是否存在 Query("page")
Query key, value 精确匹配查询参数 key 的值 Query("page", "1")
Query key, op, value 比较运算符对比查询参数 key 的数值 1 Query("page", "gt", "2")
QueryRegexp key, regex Go正则匹配查询参数 key 的值 QueryRegexp("q", ".*")
ClientIP ip... 将客户端IP与一个或多个IP或CIDR范围匹配 ClientIP("10.0.0.0/8", "::1")
Network net 匹配连接的网络类型 Network("tcp")
Proto protocol 匹配检测到的应用层协议(需开启流量嗅探) Proto("http")
BodyRegexp regex Go正则匹配缓冲的请求体前缀 3 BodyRegexp("\"model\"\\s*:\\s*\"claude-opus[^\"]*\"")
BodyJSON path, regex GJSON路径提取JSON字段并以Go正则匹配 3 BodyJSON("model", "claude.*")
BodyJSON path, op, value GJSON路径提取数值JSON字段并以比较运算符对比 3 1 BodyJSON("age", "ge", "18")
Admission name 委托给命名的准入控制器 2 Admission("block-internal")
Bypass name 委托给命名的分流规则 2 Bypass("china-mainland")

比较运算符

3.3.0

HeaderQueryBodyJSON 支持三参数形式配合比较运算符: Header("Content-Length", "gt", "1024")

运算符 匹配条件
gt 值大于
ge 值大于等于
lt 值小于
le 值小于等于
eq 值等于
ne 值不等于

值会解析为浮点数。非数值参数将静默跳过(视为不匹配)。对于多值请求头和查询参数,只要**任一**值满足比较即匹配成功。

优先级

priority (int, 默认: auto)

为避免路径重叠,节点默认按规则长度降序排序。优先级直接等于规则的长度——最长的规则 拥有最高的优先级。

设置 priority 为特定值可覆盖此行为。设置为**负数**则完全禁用自动优先级排序——所有匹配节点平等地通过选择器。

请求体大小

bodySize (int, 默认: 1MB)

用于请求体匹配器的HTTP请求体前缀最大读取大小(字节)。默认为 1MB1048576)。 上限为 10MB10485760),超过部分会被截断。

设置为 -1 可完全禁用请求体匹配。

!!! note 请求体前缀会根据 Content-Encodinggzipdeflatebrzstd)自动解压后再匹配。 仅匹配用的前缀会被解码;转发到目标的完整请求体保持原始压缩状态。

正则语法

接受正则的匹配器使用 Go的regexp语法(RE2)。 不支持 Perl 风格的先行/后行断言和反向引用。

示例

基础:按主机名路由

matcher:
  rule: Host("api.example.com")

布尔逻辑组合

matcher:
  rule: 'Method("POST") && PathPrefix("/v1/") && Header("Content-Type", "application/json")'

请求体匹配

matcher:
  rule: 'BodyJSON("output_config.effort", "^(xhigh|max)$")'
  bodySize: 65536

转发链组:按目标主机名路由

chainGroup:
  chains:
  - chain: chain-api
    matcher:
      rule: Host("api.example.com")
  - chain: chain-web
  selector:
    strategy: round

跳跃点组:按路径前缀路由

hopGroup:
  hops:
  - hop: hop-api
    matcher:
      rule: 'PathPrefix("/api/") && Host("*.example.com")'
  - hop: hop-internal
    matcher:
      rule: 'ClientIP("10.0.0.0/8", "172.16.0.0/12")'
  - hop: hop-default
  selector:
    strategy: rr

参见


  1. 3.3.0 

  2. 3.2.4 

  3. 请求体匹配器需要在处理器上开启 sniffing: true。仅读取请求体前缀用于匹配(见请求体大小),完整请求体原样转发。前缀会根据 Content-Encodinggzipdeflatebrzstd)自动解压后再匹配。 

Comments