- 合并 20+ 细粒度 spec 为粗粒度主题规范:dashboard、data-store、probe-engine、probe-api、probe-config 等 - 删除完全冗余规范:data-retention(被 probe-engine+data-store 覆盖)、backend-code-quality(DEVELOPMENT.md 已记录) - 补充 http-checker 规范至完整标准(配置+执行+expect+校验+observation),匹配代码 440 行实现 - 清理 tcp/udp/llm checker 规范中已废弃 defaults 配置段的残留 Scenario - 清理 checker-cohesion-structure 中的实现路径引用(src/server/...) - 统一所有 spec 格式(## Purpose 开头,去除 # Capability/Title 形式) - 更新 prompt-spec-review.md 审查提示文档
12 KiB
Purpose
定义 HTTP 类型拨测目标:通过 type: http 配置 HTTP/HTTPS 探测,支持请求方法、headers、body、SSL 校验、重定向和响应体大小限制,捕获 HTTP 状态码、响应头、响应体和执行耗时,按 expect 规则校验并生成 matched 判定。
Requirements
Requirement: HTTP target 配置
系统 SHALL 支持 type: http 的 target 配置,通过 http.url 描述目标 HTTP 地址,并通过可选字段控制请求方法、请求体、headers、SSL 校验、重定向和响应体大小限制。
Scenario: 解析最简 HTTP target
- WHEN YAML 中 target 配置
type: http和http.url: "https://example.com" - THEN 系统 SHALL 将其解析为 HTTP checker,并填充
method=GET、maxBodyBytes=100MB、ignoreSSL=false、maxRedirects=0、headers、body、interval、timeout、group 和 expect 配置
Scenario: HTTP target 缺少 url
- WHEN YAML 中 target 配置
type: http但缺少http.url - THEN 系统 SHALL 以配置错误退出,并提示该 target 缺少 http.url 字段
Scenario: HTTP target 覆盖请求方法
- WHEN YAML 中某个 HTTP target 显式配置
http.method: POST - THEN 该 target SHALL 使用自身 method 字段的值,而不是内置默认值 GET
Scenario: HTTP target 覆盖响应体大小限制
- WHEN YAML 中某个 HTTP target 显式配置
http.maxBodyBytes - THEN 该 target SHALL 使用自身 maxBodyBytes 字段的值,而不是内置默认值 100MB
Scenario: HTTP target 覆盖 headers
- WHEN YAML 中某个 HTTP target 显式配置
http.headers - THEN 该 target SHALL 使用自身 headers 字段的值
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 次重定向
Scenario: HTTP 序列化展示摘要
- WHEN 系统同步 HTTP target 到 targets 表
- THEN
target展示摘要 SHALL 为 HTTP URL,configJSON SHALL 包含 resolved 后的 url、method、headers、body、ignoreSSL、maxBodyBytes 和 maxRedirects
Requirement: HTTP checker 执行
系统 SHALL 按 HTTP target 配置发起 HTTP 请求,使用引擎注入的 ctx.signal 响应超时。系统 SHALL 支持手动重定向跟随(redirect: "manual"),在 maxRedirects 限制内跟随 301/302/303/307/308 重定向。系统 SHALL 记录完整执行耗时和 HTTP observation,并在网络错误、超时、响应体超限或字符编码不支持时产生结构化失败信息。
Scenario: HTTP 请求成功
- WHEN HTTP target 指向可正常响应的 HTTP 服务,且未配置 expect 或
expect.status为[200] - THEN 系统 SHALL 记录
matched=true、durationMs和包含 statusCode、headers、bodyPreview、contentType、contentLength 的 observation
Scenario: 使用 ctx.signal 响应超时
- WHEN 引擎注入的
ctx.signal在 HTTP 请求过程中 abort - THEN 系统 SHALL 记录
matched=false,observation SHALL 为 null,failure 的 kind 为error,phase 为request,message 包含超时信息
Scenario: 网络错误
- WHEN HTTP 请求因网络错误(DNS 解析失败、连接被拒绝等)失败
- THEN 系统 SHALL 记录
matched=false,observation SHALL 为 null,failure 的 kind 为error,phase 为request
Scenario: 重定向跟随
- WHEN HTTP target 配置
http.maxRedirects: 3且服务端返回 301/302/303/307/308 重定向 - THEN 系统 SHALL 在 maxRedirects 限制内自动跟随重定向,并返回最终响应供 expect 校验
Scenario: 重定向次数耗尽
- WHEN HTTP target 配置
http.maxRedirects: 1且服务端返回超过 1 次重定向 - THEN 系统 SHALL 将最后一次重定向响应作为最终结果返回,不继续跟随
Scenario: POST 重定向为 GET
- WHEN HTTP target 使用 POST 方法且收到 301 或 302 重定向,或收到 303 重定向
- THEN 系统 SHALL 将后续请求方法改为 GET,移除 Content-Type 和 Content-Length 请求头,并移除 body
Scenario: 跨域重定向移除敏感头
- WHEN 重定向到不同 origin 的目标
- THEN 系统 SHALL 移除 Authorization 和 Cookie 请求头
Scenario: 响应体读取与大小限制
- WHEN HTTP target 配置了 body expect 且响应体未超过
maxBodyBytes - THEN 系统 SHALL 读取完整响应体,按 Content-Type 字符编码解码,并用于 body expect 校验
Scenario: 响应体超过大小限制
- WHEN HTTP target 配置了 body expect 且响应体超过
maxBodyBytes - THEN 系统 SHALL 停止读取,记录
matched=false,failure 的 kind 为error,phase 为body,message 包含响应体超过大小限制的信息
Scenario: 不支持的字符编码
- WHEN HTTP 响应的 Content-Type 指定了不支持的 charset
- THEN 系统 SHALL 记录
matched=false,failure 的 kind 为error,phase 为body,message 包含不支持的字符编码信息
Scenario: 无 body expect 时不读取响应体
- WHEN HTTP target 未配置
expect.body或 body expect 为空数组 - THEN 系统 SHALL NOT 读取响应体内容,bodyPreview SHALL 为 null
Scenario: GET/HEAD 请求不发送 body
- WHEN HTTP target 配置
http.method: GET或http.method: HEAD - THEN 系统 SHALL NOT 发送请求体,即使配置了
http.body
Requirement: HTTP expect 校验
系统 SHALL 支持 HTTP 专属 expect,包括 status、headers、body 和 durationMs,并按 status、headers、early-timeout(仅当配置了 body expect 时)、body、durationMs 的阶段顺序快速失败。status SHALL 保持状态码数组语义,支持精确数字(100-599)和范围模式(1xx 到 5xx),未配置时在 Resolved expect 中默认 [200]。headers SHALL 使用共享 RawKeyedExpectations 输入并在运行期使用 KeyedExpectations,header key 大小写不敏感。body MUST 使用共享 RawContentExpectations 数组输入并在运行期使用 ContentExpectations,支持直接 ValueMatcher 以及 json/css/xpath 提取器。durationMs SHALL 使用共享 RawValueExpectation 输入并在运行期使用 ValueExpectation 校验完整执行耗时。
Scenario: 默认 status 成功语义
- WHEN HTTP target 未显式配置
expect.status - THEN 系统 SHALL 在 Resolved HTTP expect 中使用默认
status: [200]进行校验
Scenario: status 精确值匹配
- WHEN HTTP target 配置
expect.status: [200, 201]且响应状态码为 201 - THEN 系统 SHALL 判定 status 阶段通过,继续后续 expect 阶段
Scenario: status 范围模式匹配
- WHEN HTTP target 配置
expect.status: ["2xx"]且响应状态码为 204 - THEN 系统 SHALL 判定 status 阶段通过
Scenario: status 不匹配快速失败
- WHEN HTTP target 配置
expect.status: [200]且响应状态码为 500 - THEN 系统 SHALL 立即返回
matched=false,failure 的 phase 为status
Scenario: headers 校验通过
- WHEN HTTP target 配置
expect.headers: {Content-Type: {contains: "application/json"}}且响应包含对应 header - THEN 系统 SHALL 判定 headers 阶段通过,header key 匹配大小写不敏感
Scenario: headers 校验失败
- WHEN HTTP target 配置
expect.headers: {X-Custom: {exists: true}}且响应不包含该 header - THEN 系统 SHALL 返回
matched=false,failure 的 phase 为headers
Scenario: body ContentExpectations 校验通过
- WHEN HTTP target 配置
expect.body: [{contains: "ok"}, {json: {path: "$.status", equals: "success"}}]且响应体满足全部条件 - THEN 系统 SHALL 判定 body 阶段通过
Scenario: body ContentExpectations 快速失败
- WHEN HTTP target 配置两条 body expectation 且第一条失败
- THEN 系统 SHALL 返回第一条失败 expectation 的 failure,phase 为
body,并 MUST NOT 执行第二条 expectation
Scenario: body 非 JSON 响应触发 JSONPath 失败
- WHEN HTTP target 配置 json body expectation 但响应体不是合法 JSON
- THEN 系统 SHALL 记录
matched=false,failure 的 kind 为error,phase 为body
Scenario: early-timeout 快速失败
- WHEN HTTP target 配置了 body expect 和
expect.durationMs: {lte: 500},且请求状态码和 headers 通过后已耗时超过 500ms - THEN 系统 SHALL 在读取响应体之前判定 durationMs 超限,不读取响应体,直接返回
matched=false,failure 的 phase 为duration
Scenario: durationMs 校验
- WHEN HTTP target 配置
expect.durationMs: {lte: 1000}且完整执行耗时超过 1000ms - THEN 系统 SHALL 返回
matched=false,failure 的 phase 为duration
Requirement: HTTP checker 启动期配置校验
系统 SHALL 在启动期对 HTTP checker 的配置契约和语义执行严格校验。HTTP target 的 http 分组 SHALL 只允许 url、method、headers、body、ignoreSSL、maxBodyBytes、maxRedirects 字段。HTTP expect SHALL 只允许 status、headers、body、durationMs 字段。未知字段、非法类型、非法 URL 协议、非法 status 值、非法 maxBodyBytes、非法 ContentExpectations 和不可编译正则 MUST 导致启动期配置错误。语义校验 MUST NOT 修改 Raw HTTP expect 输入。
Scenario: http.url 为空字符串
- WHEN YAML 中 HTTP target 配置
http.url: "" - THEN 系统 SHALL 以配置错误退出,提示缺少 http.url 字段
Scenario: http.url 协议非法
- WHEN YAML 中 HTTP target 的
http.url不以http://或https://开头 - THEN 系统 SHALL 以配置错误退出,提示 URL 格式不合法
Scenario: http.url 格式非法
- WHEN YAML 中 HTTP target 的
http.url不是合法 URL - THEN 系统 SHALL 以配置错误退出,提示 URL 格式不合法
Scenario: http.maxBodyBytes 格式非法
- WHEN YAML 中 HTTP target 的
http.maxBodyBytes不是合法 size 值 - THEN 系统 SHALL 以配置错误退出,提示 maxBodyBytes 格式错误
Scenario: http 分组未知字段失败
- WHEN YAML 中 HTTP target 的
http分组包含未知字段 - THEN 系统 SHALL 以配置错误退出,提示 http 分组包含未知字段
Scenario: expect.status 数字非法
- WHEN YAML 中 HTTP target 的
expect.status包含非整数或不在 100-599 范围内的数字 - THEN 系统 SHALL 以配置错误退出,提示 status 数字不合法
Scenario: expect.status 模式非法
- WHEN YAML 中 HTTP target 的
expect.status包含不符合1xx到5xx格式的字符串 - THEN 系统 SHALL 以配置错误退出,提示 status 模式不合法
Scenario: expect.body 必须为数组
- WHEN YAML 中 HTTP target 的
expect.body已配置但不是数组 - THEN 系统 SHALL 以配置错误退出,提示 expect.body 必须为数组
Scenario: HTTP expect 未知字段失败
- WHEN YAML 中 HTTP target 的 expect 包含
connected、exitCode、maxDurationMs或其他非 HTTP expect 字段 - THEN 系统 SHALL 以配置错误退出,提示 expect 包含未知字段
Requirement: HTTP observation 与 detail
HTTP checker SHALL 在 observation 中记录 statusCode(number)、headers(Record<string, string>,截断至前 20 个)、bodyPreview(string | null,截断至前 1024 字符)、contentType(string | null)、contentLength(number | null)。API detail SHALL 由 buildDetail 从 observation 动态构造,格式为 HTTP {statusCode}。网络错误或超时导致无法收集 observation 时,observation SHALL 为 null,detail SHALL 为 null。
Scenario: 正常响应 observation
- WHEN HTTP 请求成功返回
- THEN observation SHALL 包含 statusCode、截断后的 headers、截断后的 bodyPreview、contentType 和 contentLength
Scenario: 未读取响应体时 bodyPreview 为 null
- WHEN HTTP target 未配置 body expect
- THEN observation.bodyPreview SHALL 为 null
Scenario: 请求失败 observation 为 null
- WHEN HTTP 请求因网络错误或超时失败
- THEN observation SHALL 为 null,detail SHALL 为 null
Scenario: detail 格式
- WHEN API 序列化 HTTP CheckResult
- THEN detail SHALL 为
HTTP {statusCode}格式(如HTTP 200)