## Purpose 定义 HTTP 拨测工具的 YAML 配置文件格式、解析校验规则和 CLI 启动流程。 ## Requirements ### Requirement: YAML 配置文件格式 系统 SHALL 支持通过 YAML 配置文件定义全部运行参数,包括 server 配置、runtime 配置、checker 默认值和 typed target 列表(含可选 group 字段)。target MUST 使用 `type` 字段声明 checker 类型,HTTP 领域字段 MUST 放在 `http` 分组,command 领域字段 MUST 放在 `command` 分组。HTTP target 的 `http` 分组 SHALL 支持可选的 `ignoreSSL`(布尔值)和 `maxRedirects`(非负整数)字段。 #### Scenario: 完整配置文件解析 - **WHEN** 系统启动并读取包含 server、runtime、defaults、targets(含 group 字段)的 YAML 配置文件 - **THEN** 系统 SHALL 正确解析所有字段并用于初始化服务、调度引擎和对应 checker runner #### Scenario: 最简 HTTP 配置文件解析 - **WHEN** 系统读取只包含一个 `type: http` target 和 `http.url` 的 YAML 配置文件(省略 server、runtime、defaults 和 expect) - **THEN** 系统 SHALL 使用内置默认值填充未指定的字段(host=127.0.0.1, port=3000, dir=./data, interval=30s, timeout=10s, runtime.maxConcurrentChecks=20, http.method=GET, http.maxBodyBytes=100MB, http.ignoreSSL=false, http.maxRedirects=0, group="default") #### Scenario: 最简 command 配置文件解析 - **WHEN** 系统读取只包含一个 `type: command` target 和 `command.exec` 的 YAML 配置文件 - **THEN** 系统 SHALL 使用内置默认值填充未指定的字段(interval=30s, timeout=10s, command.cwd 为配置文件所在目录, command.maxOutputBytes=100MB) #### Scenario: per-target 配置覆盖全局默认值 - **WHEN** 某个 target 指定 interval、timeout 或对应领域分组中的默认字段 - **THEN** 该 target SHALL 使用其自身的值,不受 defaults 中对应字段影响 #### Scenario: HTTP target 配置 ignoreSSL - **WHEN** YAML 配置中 HTTP target 设置 `http.ignoreSSL: true` - **THEN** 系统 SHALL 解析该字段并在执行时跳过 SSL 证书校验 #### Scenario: HTTP target 配置 maxRedirects - **WHEN** YAML 配置中 HTTP target 设置 `http.maxRedirects: 5` - **THEN** 系统 SHALL 解析该字段并在执行时允许最多跟随 5 次重定向 ### Requirement: CLI 参数 系统 SHALL 通过单一命令行参数接受 YAML 配置文件路径。 #### Scenario: 指定配置文件启动 - **WHEN** 用户执行 `./dial-server ./probes.yaml` - **THEN** 系统 SHALL 读取并解析指定路径的 YAML 文件作为配置 #### Scenario: 未提供配置文件路径 - **WHEN** 用户启动程序时未提供任何命令行参数 - **THEN** 系统 SHALL 以错误退出并提示需要指定配置文件路径 #### Scenario: 配置文件不存在 - **WHEN** 用户指定的配置文件路径不存在 - **THEN** 系统 SHALL 以错误退出并提示文件不存在 ### Requirement: 配置校验 系统 SHALL 在启动时对 YAML 配置进行完整校验,校验失败时以非零状态退出并输出清晰的错误信息。 #### Scenario: target 缺少必填字段 - **WHEN** YAML 中某个 target 缺少 name 或 type 字段 - **THEN** 系统 SHALL 以错误退出,提示哪个 target 缺少哪个字段 #### Scenario: HTTP target 缺少 url - **WHEN** YAML 中某个 target 配置 `type: http` 但缺少 `http.url` - **THEN** 系统 SHALL 以错误退出,提示该 target 缺少 http.url 字段 #### Scenario: command target 缺少 exec - **WHEN** YAML 中某个 target 配置 `type: command` 但缺少 `command.exec` - **THEN** 系统 SHALL 以错误退出,提示该 target 缺少 command.exec 字段 #### Scenario: target type 非法 - **WHEN** YAML 中某个 target 的 type 不是 `http` 或 `command` - **THEN** 系统 SHALL 以错误退出,提示不支持的 target type #### Scenario: target name 重复 - **WHEN** YAML 中存在两个 name 相同的 target - **THEN** 系统 SHALL 以错误退出,提示重复的 name #### Scenario: group 字段类型校验 - **WHEN** YAML 中某个 target 的 `group` 字段不是字符串 - **THEN** 系统 SHALL 以错误退出并提示 group 字段类型错误 #### Scenario: interval 格式非法 - **WHEN** interval 或 timeout 值不是有效的时长格式(如 `30s`、`5m`、`500ms`) - **THEN** 系统 SHALL 以错误退出并提示格式错误 #### Scenario: maxConcurrentChecks 非法 - **WHEN** runtime.maxConcurrentChecks 不是正整数 - **THEN** 系统 SHALL 以错误退出并提示 runtime.maxConcurrentChecks 格式错误 #### Scenario: size 格式非法 - **WHEN** maxBodyBytes 或 maxOutputBytes 值不是有效的 size 格式 - **THEN** 系统 SHALL 以错误退出并提示支持 B、KB、MB、GB 格式 #### Scenario: HTTP method 非法 - **WHEN** YAML 中某个 HTTP target 的 `http.method` 不是 GET、HEAD、POST、PUT、PATCH、DELETE、OPTIONS 之一 - **THEN** 系统 SHALL 以错误退出,提示该 target 的 method 不合法 #### Scenario: URL 格式非法 - **WHEN** YAML 中某个 HTTP target 的 `http.url` 不以 `http://` 或 `https://` 开头 - **THEN** 系统 SHALL 以错误退出,提示该 target 的 URL 格式不合法 #### Scenario: maxRedirects 非法 - **WHEN** YAML 中某个 HTTP target 的 `http.maxRedirects` 为负数 - **THEN** 系统 SHALL 以错误退出,提示该 target 的 maxRedirects 必须为非负整数 #### Scenario: maxRedirects 非整数非法 - **WHEN** YAML 中某个 HTTP target 的 `http.maxRedirects` 不是非负整数(如 `1.5` 或 `"5"`) - **THEN** 系统 SHALL 以错误退出,提示该 target 的 maxRedirects 必须为非负整数 #### Scenario: ignoreSSL 类型非法 - **WHEN** YAML 中某个 HTTP target 的 `http.ignoreSSL` 不是布尔值 - **THEN** 系统 SHALL 以错误退出,提示该 target 的 ignoreSSL 必须为布尔值 #### Scenario: status 模式非法 - **WHEN** YAML 中某个 HTTP target 的 `expect.status` 包含不符合 `数字xx` 格式的字符串(如 `"abc"`、`"2x"`) - **THEN** 系统 SHALL 以错误退出,提示该 target 的 status 模式不合法 ### Requirement: size 配置解析 系统 SHALL 支持使用单位字符串配置读取上限,单位包括 `B`、`KB`、`MB` 和 `GB`。 #### Scenario: 解析 MB - **WHEN** YAML 中配置 `maxBodyBytes: "100MB"` - **THEN** 系统 SHALL 将其解析为 104857600 bytes #### Scenario: 解析 KB - **WHEN** YAML 中配置 `maxOutputBytes: "512KB"` - **THEN** 系统 SHALL 将其解析为 524288 bytes ### Requirement: runtime 并发配置 系统 SHALL 支持 `runtime.maxConcurrentChecks` 配置全局最大并发检查数。 #### Scenario: 使用默认并发限制 - **WHEN** YAML 中未配置 runtime.maxConcurrentChecks - **THEN** 系统 SHALL 使用默认值 20 #### Scenario: 配置并发限制 - **WHEN** YAML 中配置 `runtime.maxConcurrentChecks: 5` - **THEN** 系统 SHALL 将全局最大并发检查数设置为 5 ### Requirement: YAML 配置使用 Bun 内置解析 系统 SHALL 使用 Bun 内置的 `Bun.YAML.parse()` 解析配置文件,不引入外部 YAML 解析库。 #### Scenario: 解析 YAML 内容 - **WHEN** 系统读取 YAML 文件内容 - **THEN** 系统 SHALL 调用 `Bun.YAML.parse()` 将内容解析为配置对象 ### Requirement: expect 配置增强 系统 SHALL 支持 typed target 的领域专用 expect 配置,包括 HTTP 的 `status`(支持精确数字和范围模式)、`headers`、`body` 和 command 的 `exitCode`、`stdout`、`stderr`。内容类 expect MUST 使用数组表达配置顺序。 #### Scenario: 解析 HTTP expect 配置 - **WHEN** YAML 配置文件中 HTTP target 的 expect 包含 status、headers、body 规则数组及内部方法 - **THEN** 系统 SHALL 正确解析并存储为 HTTP target 的 expect 字段 #### Scenario: 解析 command expect 配置 - **WHEN** YAML 配置文件中 command target 的 expect 包含 exitCode、stdout 和 stderr 规则数组 - **THEN** 系统 SHALL 正确解析并存储为 command target 的 expect 字段 #### Scenario: 解析 body 有序规则数组 - **WHEN** YAML 中 HTTP target 配置 `expect.body` 为 contains、json、regex 三个数组项 - **THEN** 系统 SHALL 保留数组顺序,供执行阶段按配置顺序快速失败 #### Scenario: 不配置 HTTP status - **WHEN** HTTP target 未配置 `expect.status` - **THEN** 系统 SHALL 在执行 expect 时使用默认 `status: [200]` 语义 #### Scenario: 配置 HTTP status 范围模式 - **WHEN** HTTP target 配置 `expect.status: ["2xx"]` - **THEN** 系统 SHALL 在执行 expect 时匹配所有 200-299 状态码 #### Scenario: 配置 HTTP status 混合模式 - **WHEN** HTTP target 配置 `expect.status: ["2xx", 301]` - **THEN** 系统 SHALL 在执行 expect 时匹配所有 200-299 状态码或精确匹配 301 #### Scenario: 不配置 command exitCode - **WHEN** command target 未配置 `expect.exitCode` - **THEN** 系统 SHALL 在执行 expect 时使用默认 `exitCode: [0]` 语义 #### Scenario: 不配置 expect - **WHEN** target 未配置任何 expect 规则 - **THEN** 系统 SHALL 正常处理,expect 字段为 undefined