# HTTP Client 应用程序实施计划 ## 项目概述 创建一个类似 IntelliJ IDEA HTTP Client 的 BS 架构应用程序,支持 .http 文件解析和执行。 ## 核心兼容范围 项目目标为:**完整兼容 IntelliJ IDEA HTTP Client 的核心使用方式,产品目标版本以“全部支持”为目标,不做语法子集裁剪。** 兼容范围包括但不限于: * [ ] 支持标准 `.http` / `.rest` 文件解析 * [ ] 支持单文件内多个请求块及 `###` 分隔语法 * [ ] 支持请求命名、请求注释、请求描述信息展示 * [ ] 支持全部常见 HTTP 方法及自定义方法 * [ ] 支持 URL、Header、Query、Body 中的变量引用与替换 * [ ] 支持环境变量、全局变量、文件内变量及变量覆盖规则 * [ ] 支持 JSON、XML、Text、Form URL Encoded、Multipart Form Data、二进制文件等请求体类型 * [ ] 支持引用外部文件作为请求体或表单字段内容 * [ ] 支持 Cookie、重定向、代理、超时、SSL/TLS、客户端证书等常见请求配置 * [ ] 支持响应结果查看、Header/Cookie 展示、格式化预览、响应时间与大小统计 * [ ] 支持请求前置脚本、请求后置脚本、断言、链式请求、响应数据提取与变量回填 * [ ] 支持从当前光标位置识别并执行当前请求,行为与 IntelliJ IDEA HTTP Client 保持一致 * [ ] 支持常见语法错误提示,并尽可能与 IntelliJ IDEA HTTP Client 的解析行为保持一致 * [ ] 支持导出 curl、导入常见 HTTP 请求定义,尽量保持与原始请求语义一致 * [ ] 支持导入 OpenAPI 3.0 / 3.1 契约文件,并生成 `.http` 请求模板、Mock 规则骨架和响应 Schema 校验能力 兼容性要求: * [ ] 功能设计优先遵循 IntelliJ IDEA HTTP Client 的行为模型,新增自定义语法前必须保证不破坏原有兼容性 * [ ] 若遇到 IntelliJ IDEA HTTP Client 的边界语法或特殊行为,应以兼容为第一原则,不以“简化实现”为理由降级支持 * [ ] 所有解析器、执行器、前端交互设计均需以兼容性测试用例驱动,建立覆盖常见语法与边界场景的回归测试集 * [ ] 发布前需使用真实 `.http` 示例文件进行兼容性验收,确保常用工作流可直接迁移 ### 兼容矩阵要求 * [ ] 文档需维护一份可持续更新的 IntelliJ IDEA HTTP Client 兼容矩阵,按“语法项 / 是否支持 / 差异说明 / 测试用例”逐项列出 * [ ] 兼容矩阵至少覆盖:请求分隔、请求命名、注释、变量声明与引用、环境文件、脚本块、断言、文件引用、multipart、重定向、Cookie、SSE、WebSocket、curl 导出、Postman 导入、OpenAPI 导入 * [ ] 对于暂未完全一致的行为,必须在兼容矩阵中记录具体差异、影响范围和回归用例,不能只写“部分支持” ### 解析器 AST 约束 * [ ] `.http` / `.rest` 解析器需输出稳定 AST,不直接将文本解析结果绑定到执行器内部结构 * [ ] AST 至少包含:文件、请求块、注释、请求名称、方法、URL、Header、Body、变量引用、脚本块、断言块、源代码位置 * [ ] AST 节点必须保留 `range` 信息,至少包含起始行列、结束行列、起始 offset、结束 offset * [ ] AST 需支持错误恢复;单个请求块解析失败时,不应阻断同文件其他请求块的识别 * [ ] 前端当前请求定位、语法高亮、错误标记、变量预览应尽量复用后端 AST 或等价结构,避免前后端各自实现不一致的解析逻辑 * [ ] 解析器输出需可序列化为 JSON,用于 API 调试、测试快照与前端辅助展示 ### 需求追踪与决策记录 * [ ] 需求、任务、测试和验收需建立可追踪关系,避免实现阶段出现“做了功能但找不到验收依据”的情况 * [ ] 核心需求建议使用稳定编号,例如 `REQ-CORE-*`、`REQ-FILE-*`、`REQ-EXEC-*`、`REQ-MOCK-*`、`REQ-OPENAPI-*`、`REQ-LOAD-*`、`REQ-UI-*` * [ ] MVP 任务编号需能映射到至少一个需求编号和至少一个测试或验收项 * [ ] 兼容矩阵中的每一项都应具备对应 fixture 或测试用例路径,不能只停留在文档描述 * [ ] 产品目标版本增强项如果暂未进入 MVP,需在矩阵或实施阶段中明确归属,避免被误判为 MVP 缺失 * [ ] 关键架构决策需记录为 ADR,默认路径为 `docs/decisions/ADR-{number}-{topic}.md` * [ ] ADR 至少记录:状态、背景、决策、备选方案、影响范围、后续迁移成本 * [ ] 已确定的关键决策至少包括:纯 Go 本地服务 + 浏览器前端、REST 控制面 + WebSocket 事件流、SQLite 仅做索引/缓存/命中日志、工作区文件作为事实源 * [ ] 若后续需求与已记录 ADR 冲突,应先更新 ADR 和影响说明,再修改实现计划 ## 技术栈 * **后端**: Go (Gin 框架) * **前端**: Vue 3 + TypeScript + Vite * **本地集成**: 原生 Go + 系统托盘库 (systray) * **HTTP 解析**: Go 自定义 .http 文件解析器 * **架构**: 本地 Go 服务 + 浏览器前端,后端提供 Web 服务与静态资源托管 ## 项目结构 ``` api-client/ ├── backend/ │ ├── cmd/api-client/ # 本地服务入口 │ ├── internal/api/ # REST API 与 WebSocket handler │ ├── internal/app/ # 应用启动、依赖装配、生命周期管理 │ ├── internal/parser/ # .http / .rest 解析器与 AST │ ├── internal/workspace/ # 工作区模型、文件扫描、路径解析 │ ├── internal/filestore/ # 原子写入、contentHash、外部变更检测 │ ├── internal/execution/ # Execution 状态机、调度、结果固化 │ ├── internal/eventbus/ # 实时事件、重放、背压与订阅管理 │ ├── internal/runtime/ # JavaScript 脚本运行时与内置 API │ ├── internal/httpclient/ # HTTP 请求发送、TLS、代理、Cookie │ ├── internal/mock/ # Mock Server、规则匹配、命中日志 │ ├── internal/openapi/ # OpenAPI 导入、同步、diff、Schema 校验 │ ├── internal/cacheindex/ # SQLite 索引、缓存索引、迁移 │ ├── internal/tray/ # 系统托盘与单实例协作 │ └── internal/model/ # 跨模块共享模型与错误码 ├── frontend/ │ ├── src/app/ # 应用入口、路由、全局状态装配 │ ├── src/shared/ # 通用组件、工具、API client、类型 │ ├── src/features/editor/ # 请求编辑器、当前请求定位、变量预览 │ ├── src/features/response/ # 响应查看、流式渲染、Schema 校验结果 │ ├── src/features/history/ # 历史列表与详情 │ ├── src/features/environment/# 环境管理 │ ├── src/features/mock/ # Mock 管理页 │ ├── src/features/openapi/ # OpenAPI 管理页 │ ├── src/features/loadtest/ # 压测配置与报告 │ └── public/ ├── contracts/ # 本应用 REST API OpenAPI 契约与生成配置 ├── fixtures/ # 测试夹具与快照 ├── scripts/ # 构建、生成、校验脚本 └── build/ # 打包输出与安装资源 ``` ### 后端模块边界 * [ ] `api` 仅负责 HTTP handler、参数绑定、响应 envelope 与错误映射,不直接读写工作区文件或 SQLite * [ ] `parser` 仅负责 `.http` / `.rest` 文本到 AST 的解析、错误恢复和源位置映射,不负责变量替换和请求发送 * [ ] `workspace` 负责工作区根目录、相对路径、符号链接解析、文件扫描和最近文件来源抽象 * [ ] `filestore` 负责文件读取、原子写入、`contentHash`、外部变更检测、文件版本,不理解 Mock、OpenAPI 或环境变量业务语义 * [ ] `execution` 负责 Execution 生命周期、队列调度、取消、超时、父子任务、结果固化,不直接实现具体 HTTP transport * [ ] `eventbus` 负责事件发布、订阅、序号、重放、背压和 WebSocket fan-out,不包含业务执行逻辑 * [ ] `runtime` 负责 JavaScript 运行时、脚本上下文、内置 API 和脚本超时,不直接访问浏览器环境 * [ ] `httpclient` 负责最终 HTTP 请求发送、连接复用、TLS、代理、Cookie、重定向和响应流读取 * [ ] `mock` 负责 Mock Server、规则加载、匹配、模板渲染、代理回退和命中日志;规则事实源仍通过 `filestore` 写入 `.mock.json` * [ ] `openapi` 负责目标接口 OpenAPI 文件解析、导入预览、同步 diff、请求模板生成、Mock 骨架生成和 Schema 校验 * [ ] `cacheindex` 负责 SQLite schema、索引重建、缓存记录、迁移和保留策略,不保存工作区事实源数据 * [ ] `tray` 仅负责系统托盘、单实例唤起、打开浏览器和退出服务,不持有业务状态 ### 前端模块边界 * [ ] `shared/api` 负责统一 REST client、WebSocket client、请求 envelope、错误码类型和重试策略 * [ ] `features/editor` 负责文件编辑、语法高亮、当前请求定位、请求块操作和变量预览 * [ ] `features/response` 负责普通响应、流式响应、SSE / WebSocket 会话视图、Schema 校验结果和大响应分段渲染 * [ ] `features/history` 负责历史列表、历史详情、重新执行、打开源文件和定位请求块 * [ ] `features/environment` 负责环境变量文件的展示、编辑、导入导出和默认环境选择 * [ ] `features/mock` 负责 Mock Server 状态、规则编辑、优先级排序、命中日志和规则文件保存重载 * [ ] `features/openapi` 负责 OpenAPI 源列表、导入向导、同步预览、diff 视图和生成目标选择 * [ ] `features/loadtest` 负责压测配置、实时指标、报告展示和采样明细,不直接调普通执行接口模拟压测 * [ ] 前端不得重复实现 `.http` 完整解析器;当前请求定位、错误标记和变量预览应优先消费后端 AST 或后端等价解析结果 ## 文件管理约束 * [ ] `.http` / `.rest` 文件以本地工作区文件形式管理,不存入数据库 * [ ] 应用负责本地文件的打开、保存、另存为、最近文件记录与目录浏览 * [ ] 应用负责检测文件外部变更,并提示用户重新加载或保留当前未保存内容 * [ ] 应用不提供应用内三方合并或冲突解决界面 * [ ] 文件冲突统一通过 `Git` 同步、合并与解决,应用仅提供必要的变更提示 * [ ] 请求历史索引可存入 SQLite;环境变量与项目配置以工作区 JSON 文件为准;原始 `.http` 文件内容仍以本地文件为准 * [ ] 环境变量、项目配置、Mock 规则等可版本管理数据默认保存为工作区文件,文件冲突统一通过 Git 处理 * [ ] OpenAPI 契约文件默认以本地工作区文件形式管理,应用可读取、导入、同步和生成派生产物,但不将原始 OpenAPI 内容写入 SQLite ### 文件写入一致性 * [ ] 所有工作区事实源文件保存均需采用原子写入:先写入同目录临时文件,校验成功后再执行原子替换 * [ ] 文件保存失败时不得破坏原文件;失败后需保留可理解错误,并尽量清理临时文件 * [ ] 文件保存请求需携带 `baseVersion` 或 `contentHash`,用于检测保存期间的外部变更 * [ ] 若保存时发现目标文件已被外部修改,应用不得静默覆盖,需提示用户重新加载、另存为或交给 Git 合并 * [ ] `.http-client/environments.json`、`.http-client/settings.json`、`.http-client/mocks/**/*.mock.json` 均需遵循同一套原子写入和冲突检测规则 * [ ] `.http-client/openapi/sources.json` 需遵循同一套原子写入和冲突检测规则,用于保存 OpenAPI 源文件映射与同步配置 ### 文本编码与格式约束 * [ ] 工作区事实源文本文件默认使用 `UTF-8` 编码保存 * [ ] 读取 `.http` / `.rest` 文件时应兼容带 BOM 的 UTF-8 文件,保存时默认不主动添加 BOM * [ ] 文件保存时应尽量保持原文件换行风格;新建文件默认使用 `LF` * [ ] `.http-client/*.json` 文件保存时需使用稳定缩进,默认 `2` 个空格,并保持字段顺序稳定,减少 Git diff 噪音 * [ ] JSON 文件不得写入注释;若需要备注说明,应使用显式字段,例如 `description` * [ ] 生成的 `.http` 文件需包含来源注释和更新时间,但不得写入机器本地绝对路径,避免多人协作时产生无意义 diff * [ ] 二进制响应体、Mock 静态资源和缓存文件不得被误判为文本文件进行格式化 ### 工作区配置 Schema * [ ] `.http-client/environments.json`、`.http-client/settings.json`、`.http-client/mocks/**/*.mock.json`、`.http-client/openapi/sources.json` 均需具备明确 `schemaVersion` * [ ] 工作区 JSON 文件需具备对应 JSON Schema 草案,默认保存到 `contracts/workspace-json-schemas/` * [ ] 应用保存工作区 JSON 前必须执行基础 schema 校验,失败时不得覆盖原文件 * [ ] 应用读取高版本 `schemaVersion` 文件时,默认只读或拒绝写入,并提示当前应用版本不支持该 schema * [ ] 应用读取低版本 `schemaVersion` 文件时,可执行自动迁移;迁移前必须备份原文件 * [ ] JSON Schema 需覆盖必填字段、枚举值、默认值、路径字段格式和数组元素结构 * [ ] 测试夹具中的工作区 JSON 文件需通过 schema 校验,防止示例与真实格式漂移 ### 工作区模型 * [ ] 应用以“工作区目录”为主要操作单位,同时支持直接打开单个 `.http` / `.rest` 文件 * [ ] 当用户直接打开单个文件时,应自动以该文件所在目录作为临时工作区根目录 * [ ] 相对路径解析默认以当前请求文件所在目录为第一基准,以当前工作区根目录为第二基准 * [ ] 文件引用、脚本引用、外部请求体引用均需明确遵循统一的相对路径解析规则 * [ ] MVP 阶段支持单工作区模型;多工作区并行打开不纳入当前范围 * [ ] 是否允许访问工作区外文件需提供明确配置项,默认允许用户显式选择工作区外文件,但界面需给出路径提示 * [ ] 若遇到符号链接、快捷方式或软链接路径,应统一解析到真实路径后再执行文件访问与变更检测 ### 文件监听与增量索引 * [ ] 后端需提供工作区文件监听能力,监听范围至少覆盖已打开的 `.http` / `.rest` 文件、`.http-client/environments.json`、`.http-client/settings.json`、`.http-client/mocks/**/*.mock.json`、`.http-client/openapi/sources.json` 和已登记 OpenAPI 源文件 * [ ] 文件监听事件需做去抖处理,默认去抖窗口为 `300ms`,避免保存过程中的多次底层事件触发重复解析和重复提示 * [ ] 文件监听不应直接覆盖编辑器内容;若当前文件存在未保存修改,仅提示外部变更并提供重新加载入口 * [ ] 外部文件变更后应优先执行增量索引:单个 `.http` 文件变更仅重建该文件 AST 与请求索引,单个 `.mock.json` 变更仅重建对应 Mock 规则索引,单个 OpenAPI 源变更仅重建对应 source 与 operation 索引 * [ ] 若增量索引失败,需记录错误摘要并允许用户触发全量 `POST /api/indexes/rebuild` * [ ] Git 分支切换、批量拉取、批量替换等可能产生大量文件变更时,应用应合并通知为一次“工作区发生大量变更”提示,并建议重建索引 * [ ] 文件监听可按平台差异采用不同底层实现,但对上层统一输出:`created`、`updated`、`deleted`、`renamed`、`unknown` 五类事件 ## 本地服务与执行模型 ### 本地服务约束 * [ ] 应用以后端本地服务形式运行,前端通过浏览器访问本地页面 * [ ] 本地服务负责提供 API、事件通道、静态资源托管、文件访问与执行调度能力 * [ ] 本地服务默认单实例运行,重复启动时应复用已有实例并直接打开应用页面 * [ ] 本地服务启动后默认自动打开浏览器页面,用户关闭浏览器后服务可继续驻留后台 * [ ] 首次启动时若默认端口被占用,应自动选择可用端口并更新应用页面打开地址 * [ ] 若检测到已有本应用实例正在运行,则始终复用该实例,不再新开服务进程或重新选择端口 ### 本地服务启动协议 * [ ] 默认监听地址为 `127.0.0.1` * [ ] 默认端口为 `32180` * [ ] 若默认端口不可用,端口探测范围为 `32181-32200` * [ ] 浏览器打开地址格式为 `http://127.0.0.1:{port}/` * [ ] 单实例发现优先使用本地锁文件与端口探测结合的方式 * [ ] 服务启动成功后需写入运行时元信息文件,至少包含端口、进程 ID、启动时间、数据目录 ### 执行模型总览 * [ ] 所有请求执行统一抽象为 `Execution` * [ ] 前端发起执行时,后端先创建执行任务并返回 `executionId`,不直接以同步接口返回完整响应 * [ ] REST API 负责执行创建、执行查询、执行取消、历史查询、文件管理、环境管理等控制面能力 * [ ] WebSocket 负责执行过程中的实时事件推送,包括状态变化、流式响应、脚本日志、断言结果、最终完成事件 * [ ] 单请求、批量请求、链式请求、SSE、WebSocket 会话、压测执行均复用同一套执行模型 ### Execution 类型 * [ ] `http`: 单次 HTTP 请求执行 * [ ] `batch`: 批量请求执行,包含多个子执行任务 * [ ] `chain`: 链式请求执行,后续步骤可依赖前序步骤变量提取结果 * [ ] `sse`: Server-Sent Events 长连接执行 * [ ] `websocket`: WebSocket 会话执行 * [ ] `load-test`: 对目标接口发起轻量压测执行 * [ ] `mock-server`: 本地 Mock Server 运行任务 ### Execution 状态机 * [ ] `pending`: 任务已创建,等待调度 * [ ] `running`: 任务已进入解析、变量替换、脚本执行、请求发送等阶段 * [ ] `streaming`: 已开始持续接收响应内容或实时消息 * [ ] `completed`: 执行成功结束,最终结果已固化 * [ ] `failed`: 执行失败,包括解析失败、脚本失败、请求失败、断言失败等 * [ ] `cancelled`: 执行被用户主动取消或被父任务取消 * [ ] 状态流转至少支持:`pending -> running -> completed/failed/cancelled`,以及 `running -> streaming -> completed/failed/cancelled` ### REST API 设计 * [ ] `POST /api/executions`: 创建执行任务,返回 `executionId` * [ ] `GET /api/executions/:id`: 查询执行状态、当前阶段、开始时间、结束时间、错误摘要 * [ ] `POST /api/executions/:id/cancel`: 取消执行任务 * [ ] `GET /api/executions/:id/result`: 获取最终结果快照,用于页面刷新恢复与历史回看 * [ ] `GET /api/history`: 分页查询执行历史 * [ ] `GET /api/history/:id`: 查询历史执行详情 * [ ] `GET /api/events/ws`: 建立全局 WebSocket 事件通道 * [ ] `GET /api/files/*`: 本地文件与工作区读取接口 * [ ] `POST /api/files/save`: 文件保存接口 * [ ] `GET /api/environments`: 环境列表与变量读取接口 * [ ] `POST /api/environments`: 环境创建或更新接口 * [ ] `GET /api/mocks`: 查询当前工作区 Mock 规则列表 * [ ] `POST /api/mocks`: 创建或更新 Mock 规则,并写回对应 Mock 规则文件 * [ ] `DELETE /api/mocks/:id`: 删除 Mock 规则,并写回对应 Mock 规则文件 * [ ] `GET /api/mock-files`: 查询当前工作区 Mock 规则文件列表 * [ ] `POST /api/mock-files/save`: 保存当前工作区 Mock 规则文件 * [ ] `POST /api/mock-files/reload`: 从工作区 Mock 规则文件重新加载并重建索引 * [ ] `POST /api/mock-files/preview`: 预览 Mock 规则文件变更,返回新增、更新、冲突、跳过数量 * [ ] `POST /api/mock-server/start`: 启动当前工作区 Mock Server * [ ] `POST /api/mock-server/stop`: 停止当前工作区 Mock Server * [ ] `GET /api/mock-server/status`: 查询 Mock Server 状态 * [ ] `GET /api/mock-server/hit-logs`: 分页查询 Mock Server 命中日志 * [ ] `DELETE /api/mock-server/hit-logs`: 清空当前工作区 Mock Server 命中日志 * [ ] `GET /api/openapi/sources`: 查询当前工作区已登记的 OpenAPI 契约源列表 * [ ] `POST /api/openapi/import`: 导入 OpenAPI 文件并生成 `.http` 请求模板、Mock 规则骨架、Schema 校验映射的预览结果 * [ ] `POST /api/openapi/sync/preview`: 基于已登记 OpenAPI 契约源预览同步变更,返回新增、更新、删除、冲突和不可映射项 * [ ] `POST /api/openapi/sync/apply`: 应用用户确认后的 OpenAPI 同步变更,并写入对应工作区文件 * [ ] `POST /api/openapi/diff`: 对比两个 OpenAPI 契约文件,返回接口、参数、请求体、响应 Schema 的变更摘要 * [ ] `POST /api/openapi/validate-response`: 使用 OpenAPI 响应 Schema 校验某次执行结果或用户粘贴的响应样本 * [ ] `POST /api/indexes/rebuild`: 重建当前工作区 SQLite 索引与缓存索引 ### API JSON 合同 * [ ] 所有 REST API 响应统一包含:`success`、`data`、`error`、`requestId`、`timestamp` * [ ] 成功响应中 `success=true`,`error=null`;失败响应中 `success=false`,`data=null` * [ ] 错误对象至少包含:`code`、`message`、`details`、`location` * [ ] 分页查询接口统一使用:`page`、`pageSize`、`total`、`items` * [ ] `POST /api/executions` 响应至少包含:`executionId`、`status`、`type` * [ ] `GET /api/executions/:id` 响应至少包含:`executionId`、`status`、`type`、`stage`、`startedAt`、`finishedAt`、`error` * [ ] `GET /api/executions/:id/result` 响应至少包含完整 `ExecutionResult` * [ ] `GET /api/history` 响应项至少包含:`executionId`、`type`、`status`、`requestName`、`filePath`、`environment`、`durationMs`、`startedAt` * [ ] WebSocket 事件统一采用 envelope 结构:`type`、`executionId`、`seq`、`timestamp`、`payload` * [ ] REST API 示例、OpenAPI 契约与测试快照必须统一使用响应 envelope,不允许同一接口同时存在裸对象响应与 envelope 响应 * [ ] 写入类接口需支持幂等请求标识,推荐使用 `Idempotency-Key` Header 或请求体 `operationId` * [ ] `POST /api/executions/:id/cancel`、`POST /api/mock-files/reload`、`POST /api/indexes/rebuild` 必须具备幂等语义,重复调用不得产生不一致状态 * [ ] 文件保存类接口需在请求体中携带 `baseVersion` 或 `contentHash`,并在冲突时返回 `FILE_CONFLICT` * [ ] 规则级写入接口(如 `POST /api/mocks`、`DELETE /api/mocks/:id`)需通过显式 `filePath` 或 `mock_rule_index` 定位目标规则文件,并复用同一套 `contentHash` 冲突检测 ### API 类型与契约生成 * [ ] 后端需维护 API 契约源,推荐使用 OpenAPI 3.1 或等价 JSON Schema 描述 REST 接口 * [ ] 前端 TypeScript API 类型应由 API 契约生成,避免手写重复类型 * [ ] WebSocket 事件 envelope 与 payload 类型需纳入同一契约体系,至少提供 TypeScript 类型定义 * [ ] CI 或测试流程需校验 API 契约与示例 JSON 的基本一致性 * [ ] 破坏性 API 变更需在文档中记录迁移说明 ### 内部 API 契约落地 * [ ] 本应用自身 REST API 契约默认保存为 `contracts/app-api.openapi.yaml` * [ ] WebSocket 事件 payload 类型默认保存为 `contracts/events.schema.json` 或在 `contracts/app-api.openapi.yaml` 的 `components.schemas` 中统一声明 * [ ] 前端 API 类型、请求参数类型、响应 envelope 类型必须从契约生成,生成目录默认为 `frontend/src/shared/api/generated/` * [ ] 后端 handler 层可使用契约校验工具或快照测试校验响应结构,避免文档、示例和实现漂移 * [ ] 生成代码不得手工编辑;如需改类型,应修改契约源并重新生成 * [ ] CI 至少执行契约格式校验、示例 JSON 快照校验和前端类型生成校验 * [ ] 契约变更需在 PR 或变更说明中标记为兼容变更或破坏性变更,并说明前端影响范围 ### 目标接口 OpenAPI 文件支持 * [ ] 需明确区分两类 OpenAPI:本应用自身 REST API 的 OpenAPI 契约用于前后端类型生成;用户导入的目标接口 OpenAPI 文件用于生成请求、Mock、Schema 校验和变更对比 * [ ] 用户导入的 OpenAPI 文件定位为“接口契约来源”,不替代 `.http` / `.rest` 文件;`.http` / `.rest` 仍是实际调试、执行、脚本、断言和链式场景的主要载体 * [ ] 支持导入本地 `openapi.yaml`、`openapi.yml`、`openapi.json` 文件,产品目标版本支持 OpenAPI 3.0 与 3.1 * [ ] OpenAPI 导入需解析 `paths`、`operationId`、`tags`、`parameters`、`requestBody`、`responses`、`security` 的基础结构;`security` 字段暂不展开执行能力,仅保留为导入报告中的不可执行配置提示 * [ ] 导入后默认按 `tags` 或路径前缀生成请求分组,并生成可读的 `.http` 请求模板 * [ ] `.http` 请求模板需保留 OpenAPI 来源信息,至少包含 `sourceId`、`operationId`、`method`、`path`、`schemaRef`,用于后续同步定位 * [ ] OpenAPI 变量映射默认将 `servers[0].url` 映射为 `{{baseUrl}}`,并允许用户在导入预览中修改目标环境变量名 * [ ] OpenAPI `parameters` 需映射为 Query、Path、Header、Cookie 的请求模板占位符;必填参数需在模板中明显标记 * [ ] OpenAPI `requestBody` 需根据 `content-type` 生成 JSON、Form、Multipart 或 Raw Body 示例;多个示例存在时优先使用 `examples`,其次使用 `example`,最后根据 Schema 生成基础样例 * [ ] OpenAPI `responses` 需用于生成响应 Schema 校验映射,并可用于生成基础 Mock 响应骨架 * [ ] OpenAPI 导入不得静默覆盖已有 `.http`、Mock 规则或配置文件;所有写入前必须展示预览与冲突列表 * [ ] OpenAPI 同步需支持只新增、更新已有生成块、跳过本地已修改块三种策略;默认策略为跳过本地已修改块并提示用户确认 * [ ] OpenAPI 同步冲突统一通过文件 `contentHash` 和生成块来源标记识别;应用不提供复杂合并器,最终文件冲突仍交给 Git 处理 * [ ] OpenAPI diff 需识别新增接口、删除接口、方法变化、路径变化、参数变化、请求体变化、响应状态码变化、响应 Schema 变化,并标记潜在破坏性变更 * [ ] OpenAPI 生成的 Mock 规则默认保存到 `.http-client/mocks/openapi/{sourceName}.mock.json` * [ ] OpenAPI 响应 Schema 校验默认作为用户显式启用的断言能力,不应在普通执行中强制开启 * [ ] Schema 校验失败应生成结构化断言结果,错误码使用 `SCHEMA_VALIDATION_ERROR`,并展示字段路径、期望类型、实际值摘要 * [ ] OpenAPI 导入、同步、diff、Schema 校验均需生成导入或校验报告,报告可被前端展示,也可作为测试快照保存 ### 创建执行请求模型 * [ ] 创建执行请求至少包含:执行类型、文件路径、请求定位信息、环境名、是否流式、是否保存历史 * [ ] 请求定位信息 `requestSelector` 至少支持三种模式: * [ ] `cursor`: 根据光标行列自动识别当前请求 * [ ] `requestId`: 根据解析后的请求唯一标识执行 * [ ] `range`: 根据选区或请求块范围执行,供批量执行或选中执行扩展 * [ ] `requestId` 必须在同一文件内容未发生结构性变化时保持稳定,推荐基于文件路径、请求块起始位置、请求名称生成 * [ ] 当文件内容变化导致原 `requestId` 失效时,系统应优先尝试通过请求块位置重新定位,并在失败时返回可理解错误 * [ ] 当 `cursor`、`requestId`、`range` 同时出现时,优先级固定为:`requestId` > `range` > `cursor` ### 变量解析规则 * [ ] 变量解析需区分:全局变量、环境变量、文件内变量、运行时提取变量、链式上下文变量、脚本动态写入变量 * [ ] 变量优先级必须固定并在实现中保持一致,默认推荐顺序为:脚本动态写入变量 > 链式上下文变量 > 文件内变量 > 当前环境变量 > 全局变量 * [ ] 若同名变量在多个层级同时存在,必须以固定优先级解析,不允许根据加载顺序产生不确定结果 * [ ] 未定义变量的处理策略必须显式配置;默认行为为阻断执行并返回 `VARIABLE_ERROR` * [ ] 前置脚本写入的变量应在当前请求执行阶段立即生效;后置脚本写入的变量应在后续请求或链式后续步骤中生效 * [ ] 环境切换后应立即重新计算变量解析结果,并同步刷新前端预览 * [ ] 变量语法需与 IntelliJ IDEA HTTP Client 保持一致,默认使用 `{{variableName}}` 形式 * [ ] 变量解析需支持嵌套引用检测;若出现循环引用,应立即报错并指出引用链 * [ ] 变量值默认按字符串处理;若用于 JSON、Header、Query 等上下文,不隐式推断复杂类型,除非脚本显式构造 ### 实时事件模型 * [ ] WebSocket 事件至少支持:`execution.created`、`execution.started`、`execution.progress`、`execution.log`、`execution.response.meta`、`execution.response.chunk`、`execution.assertion`、`execution.completed`、`execution.failed`、`execution.cancelled` * [ ] 所有事件均需包含 `executionId`、事件类型、事件时间戳、最小必要载荷 * [ ] 前端基于事件流增量渲染执行状态、响应内容、脚本输出与断言结果 * [ ] 当事件通道异常断开时,前端需自动尝试重连,并支持按 `executionId` 补拉最终状态或结果快照 * [ ] WebSocket 重连请求需携带客户端已收到的最新 `executionId` 与 `lastSeq`,后端优先从 `execution_event_index` 补推缺失事件 * [ ] 若缺失事件已被清理或无法补齐,后端需返回 `event.replay.unavailable` 事件,前端改为拉取 `GET /api/executions/:id/result` 最终快照 * [ ] WebSocket 事件 `seq` 在同一 `executionId` 内必须单调递增,前端需按 `seq` 去重和乱序保护 ### 事件背压与高频推送 * [ ] 事件通道需区分关键事件与可合并事件;`execution.completed`、`execution.failed`、`execution.cancelled`、`execution.assertion` 为关键事件,不得被丢弃 * [ ] `execution.progress`、压测指标、响应 chunk、脚本日志等高频事件允许合并、采样或限频,但最终结果快照必须保留完整状态摘要 * [ ] 单个前端连接的 WebSocket 待发送队列需设置上限,默认最多缓存 `1000` 条事件或 `10MB` 载荷,超过后优先丢弃可合并事件并发送 `event.backpressure` 告警 * [ ] 响应 chunk 推送默认按 `64KB` 或 `100ms` 任一条件触发批量发送,避免小包过多导致 UI 卡顿 * [ ] 压测实时指标默认按 `500ms` 聚合推送一次;用户界面刷新频率不得高于事件聚合频率 * [ ] 脚本日志默认按行聚合推送,单次执行最多保留最近 `1000` 条日志,超出后在诊断结果中标记截断 * [ ] 当前端重连后,后端优先按 `lastSeq` 补发关键事件和最终快照;对已被采样丢弃的进度事件,只保证最终聚合结果可恢复 * [ ] 若 WebSocket 客户端持续消费过慢,后端可关闭该连接并返回可理解关闭原因,前端需自动切换到轮询最终结果快照 ### 执行结果模型 * [ ] 最终结果以 `ExecutionResult` 形式固化,用于历史记录、页面刷新恢复、问题排查 * [ ] `ExecutionResult` 至少包含以下部分:`summary`、`request`、`response`、`timeline`、`assertions`、`diagnostics` * [ ] `summary` 包含任务标识、类型、状态、开始时间、结束时间、耗时、环境、文件路径、请求名称 * [ ] `request` 包含原始请求片段、解析后结构、变量替换后的最终请求、执行时环境快照 * [ ] `response` 包含状态码、状态文本、响应头、Cookie、响应体、编码、是否截断、大小 * [ ] `timeline` 包含各阶段耗时信息,如连接建立、TLS、首包、总耗时 * [ ] `assertions` 包含每条断言的名称、结果、失败原因与相关输出 * [ ] `diagnostics` 包含脚本日志、执行告警、错误码、错误消息、行列定位信息 * [ ] `ExecutionResult` 中的小体积快照属于可清理缓存,不作为唯一事实源;缓存被清理后应允许从请求文件、环境文件和响应缓存索引尽量恢复摘要 ### 批量执行模型 * [ ] 批量执行使用 `type=batch` 父任务表示,内部包含多个子执行任务 * [ ] 父任务负责顺序执行、并行执行、最大并发数、`stopOnFailure` 等调度策略 * [ ] 子任务继续复用普通 `Execution` 结构,不单独发明第二套结果模型 * [ ] 父任务取消时必须级联取消所有尚未完成的子任务 ### 链式执行模型 * [ ] 链式执行使用 `type=chain` 父任务表示,内部包含按顺序依赖的多个子执行任务 * [ ] 父任务维护 `chainContext`,用于保存变量提取结果并传递给后续步骤 * [ ] 每个链式步骤仍然独立产出执行结果,链级结果额外记录变量传递轨迹与中断位置 * [ ] 链式执行默认按顺序串行运行,前一步失败时默认中断后续步骤,除非显式配置允许继续 ### SSE / WebSocket 会话交互 * [ ] SSE 执行需支持手动断开、超时断开、收到完成条件后自动断开三种结束方式 * [ ] WebSocket 会话需支持建立连接、主动发送消息、接收消息、手动断开、异常断开提示 * [ ] WebSocket 会话消息需区分文本、JSON、二进制三类展示方式 * [ ] SSE 与 WebSocket 会话在前端需提供独立会话视图,不与普通 HTTP 响应区完全混用 * [ ] 是否将 SSE / WebSocket 会话内容写入历史记录需提供明确策略;默认保存会话摘要与关键消息,不完整持久化无限流数据 ### 执行调度策略 * [ ] 系统需定义统一的执行队列与并发上限,避免无限制并发占用本地资源 * [ ] 普通 HTTP 执行、批量子任务、链式步骤、SSE、WebSocket 会话均需纳入统一调度体系 * [ ] 长连接任务默认计入活动执行数,并支持单独配置最大长连接数 * [ ] 当达到并发上限时,新任务应进入 `pending` 队列等待,而不是直接失败 * [ ] 是否支持失败重试需提供显式配置;默认单次执行不自动重试 * [ ] 默认普通请求最大并发数为 `6` * [ ] 默认长连接最大并发数为 `2` * [ ] 默认执行队列最大等待任务数为 `100` * [ ] 默认批量执行最大并发数为 `4` ### 扩展点模型 * [ ] 后端内部需预留轻量扩展点注册机制,用于导入器、导出器、执行类型、响应查看器、Schema 校验器和 Mock 生成器扩展 * [ ] 扩展点只作为内部模块边界,不设计第三方插件市场,也不要求运行时动态加载外部代码 * [ ] 导入器扩展点统一输入源文件路径和工作区上下文,统一输出导入预览、写入计划和不可映射项报告 * [ ] 导出器扩展点统一输入解析后请求、环境快照和执行配置,统一输出目标格式文本和差异提示 * [ ] 执行类型扩展点统一接入 `Execution` 状态机、事件通道、取消信号、历史固化和调度队列 * [ ] 响应查看器扩展点统一基于 `contentType`、响应大小、编码和流式状态选择展示方式,前端不得在各页面重复判断 * [ ] Schema 校验器扩展点统一输入响应体、content-type、schemaRef 和契约来源,统一输出结构化断言结果 * [ ] Mock 生成器扩展点统一支持从 `.http` 请求、真实响应、OpenAPI operation 三类来源生成规则草案 ### 性能基准 * [ ] 解析 `1MB` `.http` 文件应在 `300ms` 内完成后端 AST 生成,解析 `10MB` 文件应在 `3000ms` 内完成并避免阻塞其他执行任务 * [ ] 打开包含 `500` 个请求块的工作区时,请求列表首次可交互时间目标不超过 `2s` * [ ] 导入包含 `1000` 个 operation 的 OpenAPI 文件时,预览生成目标时间目标不超过 `5s` * [ ] Mock Server 在 `1000` 条启用规则内的单次匹配目标耗时不超过 `5ms`,命中日志写入不得阻塞响应返回 * [ ] 普通响应体 `2MB` 以内可直接内存预览,超过阈值必须分段加载或落盘索引,避免前端一次性渲染大文本 * [ ] WebSocket 事件在普通请求执行中的端到端展示延迟目标不超过 `300ms` * [ ] 压测实时统计在默认阈值内的聚合计算不得成为主要瓶颈,报告中需记录脚本、签名、网络、聚合各阶段耗时占比 * [ ] SQLite 索引重建需按文件数量和耗时输出摘要,用于后续定位大工作区性能问题 ### 压测执行模型 * [ ] 压测执行使用 `type=load-test` 表示,目标请求仍通过 `.http` / `.rest` 文件中的请求块选择 * [ ] 压测必须由 Go 后端调度执行,前端不得通过循环调用普通执行接口模拟压测 * [ ] 压测配置至少包含:并发数、总请求数、持续时间、QPS 限制、预热时间、失败率停止阈值 * [ ] 压测执行需支持按总请求数结束、按持续时间结束、用户主动取消、失败率阈值触发停止 * [ ] 压测执行默认不保存每次请求的完整响应,仅保存统计摘要、错误摘要和少量采样明细 * [ ] 压测执行应复用变量解析、前置脚本、请求构造逻辑;后置脚本与断言默认按采样或聚合策略执行,避免压测过程过重 * [ ] 压测执行中的签名计算默认在后端执行;静态签名可在压测开始前预计算,依赖时间戳、nonce、Body 等动态数据的签名需按请求逐次计算 * [ ] 压测报告需记录签名计算耗时占比,便于判断压测瓶颈是否来自脚本或签名逻辑 * [ ] 压测过程需通过 WebSocket 事件实时推送吞吐、延迟分位数、错误率、状态码分布、已完成请求数 ### 压测保护阈值 * [ ] 默认最大压测并发数为 `100` * [ ] 默认最大压测持续时间为 `10min` * [ ] 默认最大压测请求数为 `100000` * [ ] 默认最大 QPS 限制为 `1000` * [ ] 当用户配置超过默认阈值时,界面需提示并要求显式确认 * [ ] 压测任务取消后应尽快停止新增请求,并等待已发出的请求完成或超时 ### 压测结果模型 * [ ] 压测结果需包含总请求数、成功数、失败数、错误率、总耗时、实际吞吐 * [ ] 压测结果需包含延迟统计:`min`、`avg`、`p50`、`p90`、`p95`、`p99`、`max` * [ ] 压测结果需包含状态码分布、错误类型分布、超时数量 * [ ] 压测结果需包含配置快照,便于历史回看时确认当时的并发数、QPS、持续时间和环境 * [ ] 压测历史详情页需展示趋势图或分桶数据,产品目标版本至少提供按时间窗口聚合的表格数据 * [ ] 压测结果默认只保存聚合统计、分桶指标、错误摘要和少量采样明细,不保存每次请求完整明细 * [ ] 压测采样明细需受数量上限控制,默认最多保存 `100` 条错误样本与 `100` 条成功样本 ### Mock Server 支持 * [ ] Mock 支持以本地 Mock Server 形式实现,由 Go 后端提供独立监听端口 * [ ] Mock Server 默认监听 `127.0.0.1`,端口与主应用服务端口分离 * [ ] 默认 Mock Server 端口为 `32190`,若端口被占用则在 `32191-32220` 范围内探测可用端口 * [ ] Mock 规则按工作区隔离管理,默认以工作区内 JSON 文件保存,文件可纳入 Git 版本管理 * [ ] SQLite 不作为 Mock 规则主存储,仅保存 Mock 规则索引、最近加载状态、命中日志和加速查询缓存 * [ ] Mock 规则支持拆分为多个 `.mock.json` 文件,默认加载 `.http-client/mocks/**/*.mock.json` * [ ] 多个 Mock 规则文件加载顺序按文件路径字典序稳定排序;实际命中仍以规则 `priority`、更新时间、规则 ID 作为最终决策 * [ ] 不同文件中出现相同 Mock 规则 ID 时视为冲突,应用需在加载预览和 Mock 管理页中提示,默认跳过后加载的重复规则 * [ ] 规则级新增、编辑、删除操作最终都必须落到对应 `.mock.json` 文件;SQLite 索引仅在保存成功后更新 * [ ] Mock 规则至少支持按方法、路径、Query、Header、Body 片段匹配请求 * [ ] Mock 路径匹配至少支持精确路径、路径参数、通配符三种模式,例如 `/users/1`、`/users/:id`、`/files/*` * [ ] 多条 Mock 规则同时匹配时,按 `priority` 从高到低选择;优先级相同时选择最近更新时间更晚的规则 * [ ] Mock 规则冲突需在保存时给出提示,但允许用户显式保存,用于临时覆盖旧规则 * [ ] Mock 响应至少支持状态码、Header、Body、固定延迟、响应模板 * [ ] Mock 响应 Body 支持 JSON、Text、二进制文件引用 * [ ] Mock 响应模板可读取请求路径参数、Query、Header 和 Body 摘要,用于生成动态响应 * [ ] Mock 响应模板语法优先采用轻量占位符,例如 `{{path.id}}`、`{{query.page}}`、`{{header.Authorization}}`、`{{body.userId}}` * [ ] Mock 响应模板不得执行任意 JavaScript,避免 Mock 响应生成与脚本运行时耦合;产品目标版本不支持在 Mock 模板中编写复杂控制逻辑 * [ ] Mock 规则支持启用/停用、复制、按标签分组和备注说明,便于同一接口维护多组模拟场景 * [ ] 未命中 Mock 规则时默认返回 `404`;可在工作区设置中配置代理回退到真实上游地址 * [ ] 代理回退为工作区级配置,不放在单条 Mock 规则内;启用后所有未命中请求按工作区上游地址转发 * [ ] 代理回退模式需在 UI 中明确标识,并在命中日志中区分 `mock-hit`、`mock-miss`、`proxy-hit`、`proxy-error` * [ ] Mock Server 需记录命中日志,包括时间、方法、路径、匹配规则、响应状态码、耗时 * [ ] Mock 命中日志默认仅记录请求摘要,不保存完整 Header、Body;用户可在设置中调整采样与保留策略 * [ ] Mock 命中日志需支持按数量与时间保留,默认最多保留最近 `10000` 条或 `7d` * [ ] 支持从当前 `.http` 请求生成基础 Mock 规则,默认以请求方法和 URL path 作为匹配条件 * [ ] 支持从已有响应结果生成 Mock 响应 Body、状态码与 Header,降低手写 Mock 成本 * [ ] 支持将工作区 Mock 规则保存为 JSON 文件,并支持从 JSON 文件重新加载;文件适合纳入 Git 版本管理 * [ ] Mock 规则文件保存或重载前需支持预览变更,至少展示新增、更新、冲突、跳过数量 * [ ] Mock 规则文件外部变更时,应用需提示重新加载;文件冲突不做应用内合并,统一交给 Git 处理 * [ ] Mock Server 启停状态需进入本地运行状态恢复;应用重启后默认不自动启动 Mock Server,除非用户显式配置 * [ ] 系统托盘菜单需展示 Mock Server 运行状态,并提供打开 Mock 管理页、启动、停止快捷操作 ### 错误模型 * [ ] 错误码至少包含:`PARSE_ERROR`、`VARIABLE_ERROR`、`SCRIPT_ERROR`、`REQUEST_ERROR`、`ASSERTION_ERROR`、`TIMEOUT_ERROR`、`CANCELLED`、`FILE_CONFLICT`、`SCHEMA_VERSION_UNSUPPORTED`、`SCHEMA_VALIDATION_ERROR`、`OPENAPI_PARSE_ERROR`、`OPENAPI_SYNC_CONFLICT`、`INDEX_REBUILD_ERROR`、`MIGRATION_ERROR`、`INTERNAL_ERROR` * [ ] 语法错误、变量错误、脚本错误应尽量返回可映射到编辑器的行列定位信息 ## 脚本与断言模型 ### 脚本运行时边界 * [ ] 请求前置脚本、请求后置脚本、断言统一采用 JavaScript 作为脚本语言 * [ ] 后端采用嵌入式 JavaScript 运行时执行脚本,与 Go 执行器运行在同一进程内 * [ ] 脚本运行时需提供稳定、可控、可测试的内置 API,不依赖浏览器环境 * [ ] 脚本运行时默认不提供任意文件系统访问、任意网络访问、动态模块安装等能力;本条仅定义运行时能力边界 * [ ] 脚本运行时默认不提供浏览器 DOM、`window`、`document` 等浏览器对象 ### 脚本生命周期 * [ ] 请求执行顺序为:解析请求 -> 变量替换 -> 前置脚本 -> 发送请求 -> 后置脚本 -> 断言 -> 结果固化 * [ ] 批量执行与链式执行中的每个子任务均独立执行上述生命周期 * [ ] 前置脚本可修改最终请求上下文,后置脚本可读取响应并提取变量 ### 签名计算支持 * [ ] 签名计算默认通过后端前置脚本实现,执行时机为变量替换之后、请求发送之前 * [ ] 前置脚本可读取当前请求、环境变量、文件内变量和脚本动态变量,用于构造签名原文 * [ ] 前置脚本可将签名结果写回 Header、Query、Body 或运行时变量 * [ ] 签名计算不得在前端 UI 线程中执行;普通执行、批量执行、链式执行、压测执行均由后端统一完成签名 * [ ] 内置 `crypto` API 的底层实现应优先使用 Go 原生实现,JavaScript 脚本只负责编排签名原文和写回请求 * [ ] 签名计算失败应中断当前请求,并返回 `SCRIPT_ERROR` * [ ] 签名计算相关日志需进入脚本日志,但默认仅记录计算阶段与错误摘要,不主动输出 secret、token 等原始变量值 * [ ] 压测、批量执行、链式执行中的每个子请求均需独立执行签名前置脚本,确保时间戳、nonce、签名值按请求生成 ### 脚本上下文 * [ ] 脚本上下文至少提供:当前环境变量、文件内变量、全局变量、当前请求对象、当前响应对象、链式上下文对象 * [ ] 前置脚本可访问请求对象但不可访问响应对象 * [ ] 后置脚本与断言可同时访问请求对象和响应对象 * [ ] 脚本对变量的写入应支持回填到执行上下文,以便后续链式步骤使用 ### 脚本内置 API * [ ] 至少提供读取变量、设置变量、读取请求、修改请求、读取响应、输出日志、添加断言结果等内置 API * [ ] 至少提供便于 JSON、Header、状态码校验的断言辅助 API * [ ] 脚本输出日志需进入实时事件流与最终诊断结果 * [ ] 内置 API 需提供稳定命名,至少包括:`vars.get(name)`、`vars.set(name, value)`、`request.get()`、`request.setHeader(name, value)`、`request.setQuery(name, value)`、`request.setBody(value)`、`response.get()`、`log.info(message)`、`assert.equal(actual, expected, message)` * [ ] 后置脚本与断言需支持异步 API,但必须在脚本超时范围内完成 * [ ] 若支持 `console.log`,其输出需等价映射到 `log.info` * [ ] 脚本 `assert` 失败必须生成结构化断言结果,而不是仅输出文本日志 * [ ] 内置 `crypto` API 至少提供:`crypto.hmacSha256Hex(secret, data)`、`crypto.sha256Hex(data)`、`crypto.md5Hex(data)`、`crypto.base64Encode(data)`、`crypto.uuid()` ### 脚本执行约束 * [ ] 每段脚本需设置独立超时时间,避免单个脚本阻塞整个执行任务 * [ ] 脚本执行失败应中断当前任务,并以 `SCRIPT_ERROR` 返回 * [ ] 断言失败应固化为 `ASSERTION_ERROR`,并在结果中展示断言明细 * [ ] 默认前置脚本超时时间为 `3000ms` * [ ] 默认后置脚本超时时间为 `3000ms` * [ ] 默认单次 HTTP 请求超时时间为 `30000ms` ## 数据存储模型 ### 存储边界 * [ ] 原始 `.http` / `.rest` 文件不写入 SQLite,仅以本地文件形式保存 * [ ] SQLite 仅用于索引、缓存、命中日志,不保存环境变量、项目配置、Mock 规则等事实源数据 * [ ] Mock 规则源数据默认保存为工作区 JSON 文件,不以 SQLite 作为唯一事实来源 * [ ] 环境变量与项目配置默认保存为工作区 JSON 文件,不以 SQLite 作为唯一事实来源 * [ ] OpenAPI 原始契约文件与 `.http-client/openapi/sources.json` 默认保存为工作区文件,不以 SQLite 作为唯一事实来源 * [ ] OpenAPI 派生的 `.http` 请求模板、Mock 规则文件、Schema 校验映射均按工作区文件管理,SQLite 仅保存可重建索引与摘要 ### SQLite 设计 * [ ] 至少包含以下数据表:`execution_history_index`、`execution_event_index`、`response_cache_index`、`recent_file_cache`、`mock_rule_index`、`mock_hit_logs`、`openapi_source_index`、`openapi_operation_index` * [ ] `execution_history_index` 保存执行摘要、文件路径、请求标识、环境、状态、耗时、时间范围、结果索引信息 * [ ] `execution_event_index` 保存可选事件索引信息,用于快速回放关键执行过程 * [ ] `response_cache_index` 保存响应体、事件载荷、历史快照等落盘缓存文件的索引与摘要 * [ ] `recent_file_cache` 保存最近打开文件与最近访问目录,可清理、可重建 * [ ] `mock_rule_index` 保存 Mock 规则文件索引与摘要,便于快速查询和启动 Mock Server * [ ] `openapi_source_index` 保存 OpenAPI 源文件索引与摘要,便于快速展示契约来源和同步状态 * [ ] `openapi_operation_index` 保存 OpenAPI operation 索引与生成产物摘要,便于接口搜索、diff 和同步预览 ### 索引重建策略 * [ ] SQLite 索引与缓存允许删除后重建,不得作为工作区事实源数据的唯一存储 * [ ] 索引重建需扫描 `.http-client/environments.json`、`.http-client/settings.json`、`.http-client/mocks/**/*.mock.json`、`.http-client/openapi/sources.json`、OpenAPI 源文件、响应缓存目录、事件缓存目录和最近文件缓存来源 * [ ] 索引重建完成后需返回重建摘要,至少包含扫描文件数、重建索引数、跳过数、错误数和错误摘要 * [ ] 若 SQLite 损坏,应用应提供“重建索引”恢复路径;命中日志可备份后清空,不阻断工作区继续使用 * [ ] 索引重建过程中不得修改工作区事实源 JSON 文件 ### 数据保留策略 * [ ] 请求历史需支持数量上限与清理策略,避免数据库无限增长 * [ ] 响应体过大时允许落盘为单独文件,仅在 SQLite 中保存索引与摘要信息 * [ ] 批量执行与链式执行需支持父子任务关系索引,便于查询与展示 * [ ] SSE 与 WebSocket 长连接历史需支持消息数量截断与摘要化存储,避免无限增长 * [ ] 默认历史记录保留上限为 `1000` 条 * [ ] 超出保留上限时,系统按最旧优先策略自动清理 ### 大响应体与二进制处理 * [ ] 系统需定义响应体内存预览阈值、自动落盘阈值、历史存储阈值,并在前后端保持一致 * [ ] 二进制响应默认不直接全文渲染,优先展示摘要信息、大小、MIME 类型与保存入口 * [ ] 大文本响应需支持分段加载、截断提示、另存为文件 * [ ] 历史回看时若响应体已落盘,系统需支持按索引重新加载该响应内容 * [ ] 默认响应体内存预览阈值为 `2MB` * [ ] 默认自动落盘阈值为 `5MB` * [ ] 默认历史存储阈值为 `10MB` ### 数据目录约束 * [ ] 应用需提供独立的数据目录用于 SQLite、日志、缓存响应体、运行时文件存储 * [ ] 工作区 `.http-client/` 目录仅用于保存可版本管理的事实源文件,例如环境变量、项目配置、Mock 规则与 Mock 静态资源 * [ ] 工作区 `.http-client/openapi/` 目录仅用于保存 OpenAPI 源映射、同步配置和可版本管理的派生关系,不用于保存运行时响应缓存 * [ ] SQLite、响应缓存、事件缓存、日志、诊断包、备份文件默认保存到应用数据目录,不写入工作区 `.http-client/` * [ ] Mock 静态资源属于 Mock 规则事实源,可保存在工作区 `.http-client/mocks/assets/` 并随规则文件进入 Git;运行时响应缓存不得放入该目录 * [ ] 系统托盘菜单中的“打开数据目录”需直接定位到该目录 ### 环境配置边界 * [ ] 环境配置默认按工作区维度隔离存储,不同工作区之间互不干扰 * [ ] 全局环境变量仅作为跨工作区共享的可选能力,不应覆盖工作区级环境的默认行为 * [ ] 需提供默认环境选择规则:若请求或工作区未显式指定环境,则使用最近一次选中的工作区默认环境 * [ ] 需明确请求执行时所使用的环境快照,确保历史回看时可以看到当时的实际变量值 * [ ] 环境变量需支持导入导出,导出格式需可读、可版本管理 ### 默认值与配置优先级 * [ ] 应用默认值需集中定义,后端默认值源建议位于 `backend/internal/model/defaults.go`,前端展示默认值需由 API 或生成类型获得,避免前后端各自硬编码 * [ ] 配置优先级需固定为:本次执行请求显式参数 > 当前工作区设置 > 应用内置默认值 * [ ] 环境变量解析优先级继续遵循变量解析规则,不与应用配置优先级混用 * [ ] 执行类默认值至少包含:普通请求超时、前置脚本超时、后置脚本超时、普通请求最大并发数、长连接最大并发数、批量执行最大并发数、执行队列最大等待任务数 * [ ] 压测类默认值至少包含:最大并发数、最大持续时间、最大请求数、最大 QPS、采样明细数量、实时指标推送间隔 * [ ] Mock 类默认值至少包含:默认端口、端口探测范围、未命中响应策略、命中日志保留数量、命中日志保留天数、代理回退默认状态 * [ ] OpenAPI 类默认值至少包含:生成请求目录、生成 Mock 目录、同步策略、是否默认启用 Schema 校验、默认 `baseUrl` 变量名 * [ ] UI 类默认值至少包含:最近文件数量、历史分页大小、日志展示行数、响应体内存预览阈值、响应体自动落盘阈值 * [ ] 设置页展示的默认值需说明来源:内置默认值、工作区覆盖值或本次执行覆盖值 * [ ] 用户恢复默认值时,只应删除工作区覆盖项,不应改写内置默认值或历史执行快照 ### 状态恢复策略 * [ ] 页面刷新后应恢复最近打开文件、当前选中文件、最近一次执行结果和当前环境选择 * [ ] 浏览器重新打开后应恢复最近工作区与最近会话摘要,但不强制恢复未保存临时编辑内容 * [ ] 对于正在运行中的普通执行任务,前端重新连接后应根据 `executionId` 自动恢复状态展示 * [ ] 对于 SSE / WebSocket 长连接,会话断开后默认不自动恢复原始连接,但需保留断开前的摘要与日志 * [ ] 页面刷新后应恢复编辑器光标位置、滚动位置与当前激活的响应标签页 * [ ] 未保存草稿默认仅保存在浏览器当前会话内,浏览器完全关闭后不保证恢复 ## 前端信息架构 ### 主界面布局 * [ ] 主界面采用三栏布局:左侧资源区、中间编辑区、右侧或下方响应区 * [ ] 左侧资源区至少包含文件树、最近文件、请求历史入口 * [ ] 中间编辑区使用 Monaco Editor,负责 `.http` / `.rest` 编辑、语法高亮、当前请求高亮和错误定位 * [ ] 响应区至少包含 `Body`、`Headers`、`Cookies`、`Timeline`、`Logs` 标签页 * [ ] 响应区需支持普通 HTTP 响应视图与 SSE / WebSocket 会话视图切换 ### 历史详情页 * [ ] 历史详情页需展示执行摘要、请求快照、响应快照、断言结果、脚本日志、时间线 * [ ] 历史详情页需提供重新执行、复制 curl、打开源文件、定位请求块入口 * [ ] 压测历史详情页需展示吞吐、延迟分位数、错误率、状态码分布和配置快照 ### 环境管理页 * [ ] 环境管理页需按工作区展示环境列表 * [ ] 环境变量表至少包含变量名、变量值、作用域、更新时间 * [ ] 环境管理页需提供新增、编辑、删除、导入、导出、设为默认环境操作 ### 设置页 * [ ] 设置页需包含本地服务配置、执行默认值、历史保留策略、日志与诊断入口、数据目录入口 * [ ] 设置页修改默认值后需立即影响新创建的执行任务,不影响已运行任务 ### Mock 管理页 * [ ] Mock 管理页需展示当前工作区 Mock Server 状态、访问地址、启动/停止操作 * [ ] Mock 管理页需展示 Mock 规则列表,至少包含方法、路径、状态码、延迟、启用状态、最近命中时间 * [ ] Mock 规则列表需支持按启用状态、方法、路径、标签、命中状态筛选,并支持按优先级拖拽排序 * [ ] Mock 规则编辑器需支持匹配条件、优先级、标签、备注、响应状态码、响应 Header、响应 Body、延迟、模板变量 * [ ] Mock 规则编辑器需在保存前展示冲突提示,说明可能被覆盖或覆盖其他规则的匹配范围 * [ ] Mock 响应 Body 编辑器需支持 JSON Pretty、Raw Text、二进制文件引用三种模式 * [ ] Mock 管理页需提供从最近一次真实响应生成 Mock 规则的入口 * [ ] Mock 管理页需展示命中日志,并支持按方法、路径、状态码、命中/未命中过滤 * [ ] Mock 命中日志详情需展示匹配结果、规则名称、请求摘要、响应来源、代理回退状态与耗时 * [ ] 请求编辑器需提供“从当前请求生成 Mock 规则”的入口 * [ ] Mock 管理页需提供 Mock 规则文件保存、重载、预览变更、清空命中日志操作 ### OpenAPI 管理页 * [ ] OpenAPI 管理页需展示当前工作区已登记的 OpenAPI 契约源,至少包含名称、源文件路径、版本、接口数量、最近同步时间、同步状态 * [ ] OpenAPI 管理页需提供导入本地 OpenAPI 文件、重新解析、同步预览、应用同步、移除源映射操作 * [ ] OpenAPI 导入向导需展示生成目标,包括 `.http` 请求文件、Mock 规则文件、Schema 校验映射,并允许用户逐项勾选 * [ ] OpenAPI 导入预览需展示将要新增、更新、跳过、冲突的请求块和 Mock 规则,默认不直接写入文件 * [ ] OpenAPI 同步预览需突出本地已修改请求块,默认跳过并提示用户手动确认是否覆盖 * [ ] OpenAPI diff 视图需按接口维度展示新增、删除、变更和潜在破坏性变更,支持按 tag、路径、方法过滤 * [ ] 请求编辑器需展示 OpenAPI 来源标记,并提供打开来源 operation、重新生成当前请求模板、启用响应 Schema 校验入口 * [ ] 响应区需提供“按 OpenAPI Schema 校验当前响应”入口,校验结果进入断言结果视图 * [ ] Mock 管理页需提供“从 OpenAPI 生成 Mock 骨架”的入口,并展示生成来源、operationId 和响应状态码 ### UI 空状态与异常状态 * [ ] 首次启动且未打开工作区时,主界面需展示打开工作区、打开 `.http` 文件、新建示例文件三个入口 * [ ] 当前工作区无 `.http` / `.rest` 文件时,文件树需展示空状态,并提供新建请求文件和导入 OpenAPI 的入口 * [ ] 请求文件解析失败时,编辑器需保留原文本展示,并在问题面板中列出可定位的解析错误 * [ ] 未选择请求块时,响应区需展示引导状态,提示用户将光标放到请求块内或从请求列表选择请求 * [ ] 执行中状态需清晰展示当前阶段,例如解析、变量替换、前置脚本、发送请求、接收响应、断言、固化历史 * [ ] 请求取消、超时、网络失败、脚本失败、断言失败、Schema 校验失败需使用不同错误状态展示,不得统一显示为“请求失败” * [ ] WebSocket 断开时,页面需展示连接状态和恢复动作;重连成功后需提示是否已补齐事件或已切换到结果快照 * [ ] 外部文件变更提示需区分“可安全重载”和“当前存在未保存修改”,避免用户误覆盖编辑内容 * [ ] 大响应体被截断、二进制响应不可直接预览、日志被截断时,界面需给出明确原因和可用操作 * [ ] OpenAPI 导入和同步预览为空时,需说明没有可写入变更,而不是展示空白列表 ### 快捷键与交互一致性 * [ ] 核心快捷键需集中定义,避免不同页面重复绑定造成冲突 * [ ] MVP 至少支持执行当前请求、保存当前文件、打开文件、搜索请求、取消当前执行五类快捷操作 * [ ] 快捷键触发的执行行为必须与按钮点击行为复用同一前端 action,不得分叉实现 * [ ] 弹窗、抽屉、预览面板需统一支持 `Escape` 关闭和焦点回到触发元素 * [ ] 危险或不可逆操作需提供确认,例如清空命中日志、删除 Mock 规则、覆盖本地已修改的 OpenAPI 生成块 * [ ] 前端所有异步操作需具备加载中、成功、失败、重试或关闭入口,不允许只在控制台输出错误 ### 可访问性与国际化 * [ ] 前端交互控件需具备键盘可达性,核心操作至少支持 Tab 导航与 Enter / Escape 确认取消 * [ ] 编辑器外的按钮、菜单、标签页、弹窗需具备可理解的 aria label 或等效可访问名称 * [ ] 默认界面语言为中文,文案需集中管理,避免散落在组件内部 * [ ] 产品目标版本需预留国际化结构,允许后续增加英文界面 * [ ] 时间、文件大小、耗时等显示格式需统一封装,避免各组件自行格式化 ## MVP 范围 ### MVP 必须完成 * [ ] 本地服务启动、浏览器访问、系统托盘打开页面与退出服务 * [ ] 本地工作区文件打开、保存、另存为、最近文件、外部变更提示 * [ ] `.http` 文件多请求解析、当前请求定位、变量替换、基础错误定位 * [ ] 单请求执行、执行取消、响应展示、历史记录回看 * [ ] 基础环境管理与环境切换 * [ ] 统一 `Execution` 模型、REST 控制面、WebSocket 事件通道 * [ ] JavaScript 前置脚本、后置脚本、基础断言能力 ### 产品目标版本必须完成 * [ ] 批量执行 * [ ] 链式执行 * [ ] SSE 支持 * [ ] WebSocket 会话支持 * [ ] 对目标接口发起轻量压测 * [ ] 本地 Mock Server 与 Mock 规则管理 * [ ] curl 导出、Postman collection 导入与 OpenAPI 导入同步 * [ ] 完整兼容性回归测试集 ### 可后续迭代 * [ ] 测试报告导出增强 * [ ] 更丰富的请求可视化预览 * [ ] 更完整的执行时间线分析 ## 验收标准 ### MVP 功能验收 * [ ] 用户可直接打开真实 `.http` 文件并执行当前请求,无需改写为应用私有格式 * [ ] 用户可在同一文件中执行多个请求块,并正确区分当前请求与其他请求 * [ ] 用户可切换环境后立即看到变量替换结果变化,并执行对应请求 * [ ] 用户可在长时间请求执行过程中看到实时状态变化,并主动取消任务 * [ ] 用户可在历史记录中重新查看执行结果,并恢复请求上下文 ### 产品目标版本功能验收 * [ ] 用户可对当前请求发起轻量压测,并实时查看吞吐、延迟分位数和错误率 * [ ] 用户可启动本地 Mock Server,并通过 Mock 地址访问已配置的模拟响应 * [ ] 用户可为同一路径维护多条 Mock 规则,并通过优先级控制实际命中的响应 * [ ] 用户可从真实响应生成 Mock 规则,并保存到工作区 Mock 规则文件交给 Git 管理 * [ ] 用户可导入 OpenAPI 文件生成 `.http` 请求模板,并在不覆盖本地修改的前提下预览和应用后续同步 * [ ] 用户可基于 OpenAPI 响应 Schema 校验真实响应,并在断言结果中看到字段级错误 ### 兼容性验收 * [ ] 建立一套分层的真实 `.http` 示例文件集,至少区分 `MVP` 用例集与产品目标版本完整用例集 * [ ] 每次阶段发布前均需执行对应阶段范围内的兼容性回归测试;产品目标版本发布前需执行完整兼容性回归测试 * [ ] 若发现与 IntelliJ IDEA HTTP Client 行为不一致,需记录差异并在发布前修复或明确列入已知限制 ### 质量验收 * [ ] 后端需具备解析器、执行器、脚本运行时、API 层单元测试 * [ ] 前端需具备核心组件测试与关键交互测试 * [ ] 集成测试需覆盖文件打开、请求执行、事件推送、历史回看、环境切换等主流程 * [ ] 压测测试需覆盖并发限制、QPS 限制、取消、失败率停止阈值和结果统计准确性 * [ ] Mock 测试需覆盖规则匹配、优先级冲突、未命中、代理回退、动态响应、延迟、命中日志和启停状态 ### 非功能验收 * [ ] 冷启动到本地服务可访问的目标时间不超过 `3s` * [ ] 打开 `1MB` `.http` 文件并完成请求块识别的目标时间不超过 `1s` * [ ] 普通 JSON 响应 `2MB` 以内 Pretty 展示目标时间不超过 `1s` * [ ] 空闲状态后端常驻内存目标不超过 `150MB` * [ ] 前端主要交互不应因流式响应持续追加而出现明显卡顿 * [ ] 大响应体、长连接和批量执行场景不得导致 UI 主线程长时间阻塞 * [ ] 压测执行期间前端统计展示刷新频率需受控,避免高频事件导致 UI 卡顿 ### 质量门禁与完成定义 * [ ] 每个 MVP 任务完成前必须能对应到需求编号、实现提交、测试用例和验收项 * [ ] 后端代码合入前至少通过:`go test ./backend/...`、API envelope 测试、parser golden tests、核心执行集成测试 * [ ] 前端代码合入前至少通过:`npm run test --prefix frontend`、关键组件测试、主流程 E2E 或对应替代验证 * [ ] 契约相关变更合入前必须通过内部 API OpenAPI 契约校验、前端类型生成校验和 API 示例 JSON 快照校验 * [ ] 工作区 JSON schema 变更合入前必须通过 schema 校验、低版本迁移测试和高版本拒绝写入测试 * [ ] Mock、OpenAPI、环境变量、设置文件的写入逻辑变更必须覆盖 `contentHash` 冲突检测和原子写入失败路径 * [ ] 事件流、压测、SSE、WebSocket 相关变更必须覆盖慢客户端、断线重连、取消和最终结果快照恢复 * [ ] 大响应体、二进制响应、日志截断相关变更必须覆盖阈值、落盘、截断提示和历史回看 * [ ] 任一阶段发布前需更新兼容矩阵、测试 fixture、API 示例和实施状态,避免文档与实现漂移 * [ ] 若某项验收无法自动化,需在测试记录中说明手工验证步骤、输入数据和观察结果 * [ ] 完成定义固定为:功能可用、错误可理解、状态可恢复、数据不丢失、测试有覆盖、文档已同步 ## 诊断与运维约束 ### 日志与诊断 * [ ] 系统需区分应用日志、执行日志、脚本日志、会话日志,避免所有日志混入同一输出 * [ ] 日志需至少支持 `error`、`warn`、`info`、`debug` 四级别 * [ ] 每次执行任务需具备可追踪的日志标识,便于通过 `executionId` 检索相关日志 * [ ] 设置页或托盘菜单需提供“打开日志目录”或等效入口,便于排查问题 * [ ] 用户需能够导出基础诊断信息,至少包含版本号、系统信息、最近错误摘要、最近执行日志索引 * [ ] 日志文件命名格式为 `{category}-{yyyyMMdd}.log` * [ ] 执行日志需包含 `executionId`,便于与历史记录互相定位 * [ ] 诊断包导出格式为 zip,目录结构至少包含 `summary.json`、`logs/`、`recent-errors.json`、`runtime.json` ### 故障恢复 * [ ] 本地服务异常退出后,再次启动时应提示最近一次非正常退出,并提供查看日志入口 * [ ] 若 SQLite 或缓存文件损坏,系统需给出可理解的错误提示,并提供“重建索引”恢复入口 * [ ] 重建索引失败不应阻断工作区事实源文件访问;用户仍可打开、编辑、保存 `.http` 与 `.http-client/*.json` 文件 ## 构建与发布命令 ### 本地开发命令 * [ ] 后端开发命令:`go run ./backend` * [ ] 前端开发命令:`npm run dev --prefix frontend` * [ ] 前端构建命令:`npm run build --prefix frontend` * [ ] 后端测试命令:`go test ./backend/...` * [ ] 前端测试命令:`npm run test --prefix frontend` ### 打包命令 * [ ] 统一构建命令:`npm run build --prefix frontend` 后执行 `go build ./backend` * [ ] 前端构建产物目录固定为 `frontend/dist` * [ ] 后端需将 `frontend/dist` 作为静态资源托管目录 * [ ] 产品目标版本默认将前端静态资源嵌入 Go 二进制,MVP 阶段允许以目录形式随包分发 ## 测试计划 ### 后端测试 * [ ] Parser 使用 golden tests 覆盖 `.http` / `.rest` 解析、错误定位、变量引用、请求块定位 * [ ] Executor 使用 integration tests 覆盖普通 HTTP、取消、超时、重定向、Cookie、TLS 配置 * [ ] Execution 使用状态机测试覆盖状态流转、父子任务、取消级联、队列调度 * [ ] Script runtime 使用单元测试覆盖变量读写、请求修改、响应读取、断言失败、超时 * [ ] API 层使用 handler tests 覆盖统一响应 envelope、错误模型、分页与状态查询 * [ ] OpenAPI 模块测试覆盖 3.0 / 3.1 解析、请求模板生成、Mock 骨架生成、同步预览、diff、响应 Schema 校验 ### 前端测试 * [ ] Editor 组件测试覆盖当前请求定位、错误标记、变量预览 * [ ] Response 组件测试覆盖标签页切换、Raw / Pretty / Preview、流式 chunk 增量渲染 * [ ] History 测试覆盖历史列表分页、详情回看、重新执行 * [ ] Environment 测试覆盖环境切换、变量编辑、导入导出 * [ ] Mock 管理测试覆盖规则新增、编辑、启停、优先级排序、文件保存、文件重载、命中日志过滤 * [ ] OpenAPI 管理测试覆盖导入向导、同步预览、diff 过滤、生成目标勾选、Schema 校验结果展示 ### 端到端测试 * [ ] E2E 测试覆盖打开工作区、打开 `.http` 文件、执行当前请求、查看响应、取消请求、历史回看 * [ ] 兼容性回归测试需按附录 A 的用例路径组织 * [ ] 压测 E2E 测试需覆盖创建压测、实时统计更新、主动取消、历史报告回看 * [ ] Mock E2E 测试需覆盖从请求生成 Mock 规则、从真实响应生成 Mock 规则、启动 Mock Server、访问 Mock 响应、查看命中日志、保存与重载规则文件 * [ ] OpenAPI E2E 测试需覆盖导入契约、生成 `.http` 请求、生成 Mock 骨架、执行请求、校验响应 Schema、预览同步冲突 ## 支持矩阵与发布约束 ### 平台支持矩阵 * [ ] 当前最低支持版本定义为:Windows 10、macOS 12、主流 Linux x86_64 发行版 * [ ] 推荐浏览器定义为:Chrome / Edge 最新两个稳定版本 * [ ] 对于不同平台上的托盘、文件路径、默认浏览器唤起行为差异,需建立平台差异清单 ### 打包与升级约束 * [ ] 打包产物需明确区分安装目录、应用数据目录、缓存目录、日志目录 * [ ] 版本升级时需提供 SQLite 缓存数据库迁移、工作区 JSON schema 迁移与失败回滚策略 * [ ] 升级后不得破坏现有工作区配置、环境配置、历史记录索引 * [ ] 安装包与二进制发布说明需明确首次启动行为、数据目录位置、卸载后数据保留策略 ### 导入导出映射 * [ ] curl 导出需覆盖方法、URL、Query、Header、Cookie、Body、代理和 TLS 相关配置 * [ ] curl 导出遇到无法表达的应用内部配置时,需在导出结果旁展示差异提示 * [ ] Postman collection 导入需覆盖 collection、folder、request、environment variables 的基础映射 * [ ] Postman 导入遇到不可映射字段时,不应静默丢弃,需生成导入报告 * [ ] 导入报告至少包含:成功数量、失败数量、跳过数量、不可映射字段列表、源文件路径 * [ ] 导入后的请求默认生成 `.http` 文件,原始 Postman collection 不写入数据库 * [ ] OpenAPI 导入需覆盖 `paths`、`tags`、`operationId`、`parameters`、`requestBody`、`responses`、`servers` 的基础映射 * [ ] OpenAPI 导入遇到不可映射字段时,不应静默丢弃,需生成导入报告,并在报告中标记字段路径与影响范围 * [ ] OpenAPI 导入后的请求默认生成 `.http` 文件,原始 OpenAPI 文件仍保留为工作区契约源,不写入数据库 * [ ] OpenAPI 同步需保留本地手写脚本、断言和备注,除非用户显式选择重新生成对应请求块 * [ ] OpenAPI diff 报告需区分兼容变更与潜在破坏性变更,供同步预览和发布检查复用 ## 附录 A:兼容矩阵草案 | 语法项 | 产品目标版本 | MVP | 差异说明 | 回归用例 | | --- | --- | --- | --- | --- | | `.http` 文件 | 支持 | 支持 | 无 | `compat/basic/get.http` | | `.rest` 文件 | 支持 | 支持 | 与 `.http` 同解析流程 | `compat/basic/rest-file.rest` | | `###` 请求分隔 | 支持 | 支持 | 无 | `compat/parser/multiple-requests.http` | | 请求命名 | 支持 | 支持 | 需展示在执行摘要与历史记录中 | `compat/parser/named-request.http` | | 行注释与块注释 | 支持 | 支持 | 与 IntelliJ IDEA HTTP Client 保持一致 | `compat/parser/comments.http` | | 自定义 HTTP 方法 | 支持 | 支持 | 不限制为内置方法枚举 | `compat/request/custom-method.http` | | Header 解析 | 支持 | 支持 | 支持同名 Header 多值 | `compat/request/headers.http` | | Query 参数 | 支持 | 支持 | URL 原样解析,变量替换后执行 | `compat/request/query-vars.http` | | JSON Body | 支持 | 支持 | 支持格式化预览 | `compat/body/json.http` | | XML Body | 支持 | 支持 | 支持 Raw 与 Pretty 预览 | `compat/body/xml.http` | | Text Body | 支持 | 支持 | 按文本展示 | `compat/body/text.http` | | Form URL Encoded | 支持 | 产品目标版本 | MVP 可先作为 Raw Body 执行 | `compat/body/form-url-encoded.http` | | Multipart Form Data | 支持 | 产品目标版本 | 需覆盖文本字段与文件字段 | `compat/body/multipart.http` | | 二进制 Body | 支持 | 产品目标版本 | 需结合文件引用处理 | `compat/body/binary-file.http` | | 外部文件引用 | 支持 | 产品目标版本 | 路径解析遵循工作区模型 | `compat/body/external-file.http` | | 文件内变量 | 支持 | 支持 | 参与固定优先级解析 | `compat/vars/file-vars.http` | | 环境变量 | 支持 | 支持 | 工作区级隔离 | `compat/vars/environment-vars.http` | | 全局变量 | 支持 | 产品目标版本 | 作为跨工作区可选能力 | `compat/vars/global-vars.http` | | 变量嵌套引用 | 支持 | 支持 | 循环引用需报错 | `compat/vars/nested-vars.http` | | Cookie 管理 | 支持 | 产品目标版本 | 需展示 Cookie 视图 | `compat/request/cookies.http` | | 重定向 | 支持 | 产品目标版本 | 需展示最终 URL 与跳转链 | `compat/request/redirect.http` | | 代理配置 | 支持 | 产品目标版本 | 需在请求配置中体现 | `compat/request/proxy.http` | | SSL/TLS 配置 | 支持 | 产品目标版本 | 包含跳过校验与证书配置 | `compat/request/tls.http` | | 客户端证书 | 支持 | 产品目标版本 | 证书文件按工作区路径规则解析 | `compat/request/client-cert.http` | | 前置脚本 | 支持 | 支持 | JavaScript 运行时执行 | `compat/scripts/pre-request.http` | | 后置脚本 | 支持 | 支持 | 支持变量回填 | `compat/scripts/post-request.http` | | 断言 | 支持 | 支持 | 失败生成结构化断言结果 | `compat/scripts/assertions.http` | | 链式请求 | 支持 | 产品目标版本 | 通过 `chainContext` 传递变量 | `compat/flow/chain.http` | | 批量执行 | 支持 | 产品目标版本 | 父子 `Execution` 模型 | `compat/flow/batch.http` | | SSE | 支持 | 产品目标版本 | 独立会话视图 | `compat/stream/sse.http` | | WebSocket | 支持 | 产品目标版本 | 支持收发消息与会话摘要 | `compat/stream/websocket.http` | | 轻量压测 | 支持 | 产品目标版本 | 基于 `load-test` Execution 类型 | `compat/load-test/basic-load-test.http` | | 本地 Mock Server | 支持 | 产品目标版本 | 工作区级 Mock 规则与命中日志 | `compat/mock/basic-mock.json` | | 导出 curl | 支持 | 产品目标版本 | 保持请求语义一致 | `compat/import-export/export-curl.http` | | 导入 Postman | 支持 | 产品目标版本 | 不可映射项需提示 | `compat/import-export/postman-collection.json` | | 导入 OpenAPI | 支持 | 产品目标版本 | 作为接口契约来源生成 `.http`、Mock 骨架和 Schema 校验映射 | `compat/import-export/openapi-import.yaml` | | OpenAPI 同步 | 支持 | 产品目标版本 | 预览 diff 并保护本地已修改请求块 | `compat/import-export/openapi-sync.yaml` | | OpenAPI Schema 校验 | 支持 | 产品目标版本 | 用户显式启用后生成结构化断言结果 | `compat/import-export/openapi-schema-validation.http` | ## 附录 B:API 示例 JSON ### 统一成功响应 ```json { "success": true, "data": { "executionId": "exec_01HZY7R4S7M4H4QF3W2K2N4H8A", "status": "pending", "type": "http" }, "error": null, "requestId": "req_01HZY7R4S7S0Y73ZJ81EF1Z8Y3", "timestamp": "2026-06-06T10:20:30Z" } ``` ### 统一失败响应 ```json { "success": false, "data": null, "error": { "code": "VARIABLE_ERROR", "message": "Undefined variable: token", "details": { "variableName": "token" }, "location": { "filePath": "C:/workspace/api/demo.http", "line": 8, "column": 23 } }, "requestId": "req_01HZY7R4S7S0Y73ZJ81EF1Z8Y3", "timestamp": "2026-06-06T10:20:31Z" } ``` ### 创建执行请求 ```json { "operationId": "op_exec_01HZY7R4S6", "type": "http", "filePath": "C:/workspace/api/demo.http", "requestSelector": { "mode": "cursor", "line": 18, "column": 5 }, "environment": "dev", "stream": true, "persistHistory": true } ``` ### 创建压测请求 ```json { "operationId": "op_loadtest_01HZY7R4S6", "type": "load-test", "filePath": "C:/workspace/api/demo.http", "requestSelector": { "mode": "requestId", "requestId": "req_list_users" }, "environment": "dev", "stream": true, "persistHistory": true, "loadTest": { "concurrency": 20, "totalRequests": 1000, "durationSeconds": 60, "qpsLimit": 100, "warmupSeconds": 5, "stopOnErrorRate": 0.2 } } ``` ### 查询执行状态响应 ```json { "success": true, "data": { "executionId": "exec_01HZY7R4S7M4H4QF3W2K2N4H8A", "type": "http", "status": "running", "stage": "sending", "startedAt": "2026-06-06T10:20:30Z", "finishedAt": null, "error": null }, "error": null, "requestId": "req_01HZY7R4S7S0Y73ZJ81EF1Z8Y4", "timestamp": "2026-06-06T10:20:30Z" } ``` ### WebSocket 事件 envelope ```json { "type": "execution.response.chunk", "executionId": "exec_01HZY7R4S7M4H4QF3W2K2N4H8A", "seq": 12, "timestamp": "2026-06-06T10:20:31Z", "payload": { "contentType": "application/json", "encoding": "utf-8", "chunk": "{\"id\":1,\"name\":\"demo\"}", "offset": 0, "done": false } } ``` ### 压测进度事件 ```json { "type": "execution.loadtest.progress", "executionId": "exec_01HZY7R4S7M4H4QF3W2K2N4H8B", "seq": 42, "timestamp": "2026-06-06T10:20:40Z", "payload": { "completedRequests": 500, "successRequests": 490, "failedRequests": 10, "errorRate": 0.02, "throughput": 83.3, "latency": { "avgMs": 45, "p95Ms": 120, "p99Ms": 240 }, "statusCodes": { "200": 490, "500": 10 } } } ``` ### ExecutionResult 示例 ```json { "summary": { "executionId": "exec_01HZY7R4S7M4H4QF3W2K2N4H8A", "type": "http", "status": "completed", "startedAt": "2026-06-06T10:20:30Z", "finishedAt": "2026-06-06T10:20:31Z", "durationMs": 864, "environment": "dev", "filePath": "C:/workspace/api/demo.http", "requestName": "List users" }, "request": { "raw": "GET https://api.example.com/users\nAccept: application/json", "resolved": { "method": "GET", "url": "https://api.example.com/users", "headers": { "Accept": "application/json" }, "body": null }, "environmentSnapshot": { "name": "dev", "variables": { "baseUrl": "https://api.example.com" } } }, "response": { "statusCode": 200, "statusText": "OK", "headers": { "Content-Type": "application/json" }, "cookies": [], "body": "[{\"id\":1,\"name\":\"demo\"}]", "bodyEncoding": "utf-8", "bodyTruncated": false, "size": 24 }, "timeline": { "dnsMs": null, "connectMs": 18, "tlsMs": 42, "firstByteMs": 210, "totalMs": 864 }, "assertions": [], "diagnostics": { "logs": [], "warnings": [], "error": null } } ``` ### 压测结果示例 ```json { "summary": { "executionId": "exec_01HZY7R4S7M4H4QF3W2K2N4H8B", "type": "load-test", "status": "completed", "requestName": "List users", "durationMs": 60000, "environment": "dev" }, "loadTest": { "config": { "concurrency": 20, "totalRequests": 1000, "durationSeconds": 60, "qpsLimit": 100, "warmupSeconds": 5, "stopOnErrorRate": 0.2 }, "summary": { "totalRequests": 1000, "successRequests": 980, "failedRequests": 20, "errorRate": 0.02, "throughput": 16.3 }, "latency": { "minMs": 12, "avgMs": 45, "p50Ms": 38, "p90Ms": 80, "p95Ms": 120, "p99Ms": 240, "maxMs": 500 }, "statusCodes": { "200": 980, "500": 20 }, "errors": { "REQUEST_ERROR": 20 } } } ``` ### 文件读取响应 ```json { "success": true, "data": { "filePath": "C:/workspace/api/demo.http", "workspacePath": "C:/workspace/api", "content": "GET https://api.example.com/users\nAccept: application/json", "lastModifiedAt": "2026-06-06T10:00:00Z", "version": "filever_01HZY7R4S7" }, "error": null, "requestId": "req_01HZY7R4S7S0Y73ZJ81EF1Z8Y4", "timestamp": "2026-06-06T10:20:30Z" } ``` ### 文件保存请求 ```json { "operationId": "op_save_file_01HZY7R4S7", "filePath": "C:/workspace/api/demo.http", "content": "GET https://api.example.com/users\nAccept: application/json", "baseVersion": "filever_01HZY7R4S7", "createIfMissing": false } ``` ### 环境列表响应 ```json { "success": true, "data": { "workspacePath": "C:/workspace/api", "defaultEnvironment": "dev", "items": [ { "id": "env_dev", "name": "dev", "scope": "workspace", "isDefault": true, "updatedAt": "2026-06-06T10:00:00Z" } ] }, "error": null, "requestId": "req_01HZY7R4S7S0Y73ZJ81EF1Z8Y5", "timestamp": "2026-06-06T10:20:30Z" } ``` ### 环境保存请求 ```json { "operationId": "op_save_env_01HZY7R4S8", "workspacePath": "C:/workspace/api", "filePath": "C:/workspace/api/.http-client/environments.json", "contentHash": "sha256:envhash_01HZY7R4S8", "name": "dev", "isDefault": true, "variables": [ { "name": "baseUrl", "value": "https://api.example.com", "scope": "workspace" } ] } ``` ### 历史列表响应 ```json { "success": true, "data": { "page": 1, "pageSize": 20, "total": 1, "items": [ { "executionId": "exec_01HZY7R4S7M4H4QF3W2K2N4H8A", "type": "http", "status": "completed", "requestName": "List users", "filePath": "C:/workspace/api/demo.http", "environment": "dev", "durationMs": 864, "startedAt": "2026-06-06T10:20:30Z" } ] }, "error": null, "requestId": "req_01HZY7R4S7S0Y73ZJ81EF1Z8Y6", "timestamp": "2026-06-06T10:20:30Z" } ``` ### Mock 规则保存请求 ```json { "operationId": "op_save_mock_01HZY7R4S9", "workspacePath": "C:/workspace/api", "filePath": "C:/workspace/api/.http-client/mocks/users.mock.json", "contentHash": "sha256:mockhash_01HZY7R4S9", "name": "Mock list users", "enabled": true, "priority": 100, "tags": ["users", "happy-path"], "description": "List users success response", "match": { "method": "GET", "path": "/users", "pathMode": "exact", "query": {}, "headers": {}, "bodyContains": null }, "response": { "statusCode": 200, "headers": { "Content-Type": "application/json" }, "body": "[{\"id\":1,\"name\":\"demo\"}]", "bodyType": "json", "delayMs": 100, "templateEnabled": true } } ``` ### Mock 规则文件保存请求 ```json { "operationId": "op_save_mock_file_01HZY7R4T0", "workspacePath": "C:/workspace/api", "filePath": "C:/workspace/api/.http-client/mocks/users.mock.json", "contentHash": "sha256:mockfilehash_01HZY7R4T0", "schemaVersion": 1, "updatedAt": "2026-06-06T10:20:30Z", "rules": [ { "id": "mockrule_users", "name": "Mock list users", "enabled": true, "priority": 100, "match": { "method": "GET", "path": "/users", "pathMode": "exact" }, "response": { "statusCode": 200, "headers": { "Content-Type": "application/json" }, "body": "[{\"id\":1,\"name\":\"demo\"}]", "bodyType": "json", "delayMs": 100, "templateEnabled": true } } ] } ``` ### Mock 规则文件预览请求 ```json { "workspacePath": "C:/workspace/api", "filePath": "C:/workspace/api/.http-client/mocks/users.mock.json", "mode": "preview", "rules": [ { "name": "Mock get user", "enabled": true, "priority": 200, "match": { "method": "GET", "path": "/users/:id", "pathMode": "template" }, "response": { "statusCode": 200, "headers": { "Content-Type": "application/json" }, "body": "{\"id\":\"{{path.id}}\",\"name\":\"demo\"}", "bodyType": "json", "delayMs": 0, "templateEnabled": true } } ] } ``` ### Mock 规则文件预览响应 ```json { "success": true, "data": { "created": 1, "updated": 0, "conflicted": 0, "skipped": 0, "conflicts": [] }, "error": null, "requestId": "req_01HZY7R4S7S0Y73ZJ81EF1Z8Y9", "timestamp": "2026-06-06T10:20:30Z" } ``` ### Mock Server 状态响应 ```json { "success": true, "data": { "running": true, "host": "127.0.0.1", "port": 32190, "baseUrl": "http://127.0.0.1:32190", "workspacePath": "C:/workspace/api", "ruleCount": 3, "proxyFallbackEnabled": false, "startedAt": "2026-06-06T10:20:30Z" }, "error": null, "requestId": "req_01HZY7R4S7S0Y73ZJ81EF1Z8Y7", "timestamp": "2026-06-06T10:20:30Z" } ``` ### Mock 命中日志响应 ```json { "success": true, "data": { "page": 1, "pageSize": 20, "total": 1, "items": [ { "id": "mockhit_01HZY7R4S7", "ruleId": "mockrule_users", "matched": true, "source": "mock-hit", "method": "GET", "path": "/users", "statusCode": 200, "durationMs": 101, "requestSummary": { "query": {}, "headersCount": 5, "bodySize": 0 }, "requestedAt": "2026-06-06T10:20:31Z" } ] }, "error": null, "requestId": "req_01HZY7R4S7S0Y73ZJ81EF1Z8Y8", "timestamp": "2026-06-06T10:20:31Z" } ``` ### OpenAPI 导入预览响应 ```json { "success": true, "data": { "source": { "id": "openapi_users", "name": "Users API", "sourcePath": "C:/workspace/api/openapi/users.yaml", "openapiVersion": "3.1.0", "title": "Users API", "version": "1.0.0", "operationCount": 2 }, "targets": { "requestFilePath": "C:/workspace/api/generated/openapi/users.http", "mockFilePath": "C:/workspace/api/.http-client/mocks/openapi/users.mock.json" }, "summary": { "createdRequests": 2, "updatedRequests": 0, "skippedRequests": 0, "createdMockRules": 2, "schemaMappings": 2, "unmappedFields": 1 }, "conflicts": [], "unmapped": [ { "fieldPath": "$.components.securitySchemes.ApiKeyAuth", "reason": "security scheme is recorded but not converted to executable auth config" } ] }, "error": null, "requestId": "req_01HZY7R4S7S0Y73ZJ81EF1Z8Y9", "timestamp": "2026-06-06T10:20:31Z" } ``` ### OpenAPI 同步预览响应 ```json { "success": true, "data": { "sourceId": "openapi_users", "sourcePath": "C:/workspace/api/openapi/users.yaml", "strategy": "skip-local-modified", "summary": { "created": 1, "updated": 1, "deleted": 0, "skipped": 1, "conflicted": 1, "breakingChanges": 1 }, "changes": [ { "operationId": "listUsers", "method": "GET", "path": "/users", "changeType": "updated", "breaking": false, "targetFilePath": "C:/workspace/api/generated/openapi/users.http" }, { "operationId": "createUser", "method": "POST", "path": "/users", "changeType": "updated", "breaking": true, "targetFilePath": "C:/workspace/api/generated/openapi/users.http" } ], "conflicts": [ { "operationId": "createUser", "reason": "local request block was modified after last OpenAPI sync", "targetFilePath": "C:/workspace/api/generated/openapi/users.http", "requestBlockId": "req_create_user" } ] }, "error": null, "requestId": "req_01HZY7R4S7S0Y73ZJ81EF1Z8Z0", "timestamp": "2026-06-06T10:20:31Z" } ``` ### OpenAPI Schema 校验响应 ```json { "success": true, "data": { "valid": false, "sourceId": "openapi_users", "operationId": "listUsers", "statusCode": 200, "schemaRef": "#/paths/~1users/get/responses/200/content/application~1json/schema", "errors": [ { "path": "$[0].id", "expected": "integer", "actual": "string", "actualSummary": "\"1\"" } ], "assertion": { "name": "OpenAPI response schema", "passed": false, "errorCode": "SCHEMA_VALIDATION_ERROR" } }, "error": null, "requestId": "req_01HZY7R4S7S0Y73ZJ81EF1Z8Z1", "timestamp": "2026-06-06T10:20:31Z" } ``` ## 附录 C:SQLite 表结构草案 ### `execution_history_index` | 字段 | 类型 | 说明 | | --- | --- | --- | | `id` | TEXT PRIMARY KEY | `executionId` | | `parent_id` | TEXT NULL | 父执行任务 ID | | `type` | TEXT NOT NULL | `http` / `batch` / `chain` / `sse` / `websocket` / `load-test` / `mock-server` | | `status` | TEXT NOT NULL | 执行状态 | | `request_name` | TEXT NULL | 请求名称 | | `request_id` | TEXT NULL | 请求块稳定标识 | | `file_path` | TEXT NOT NULL | 请求文件路径 | | `workspace_path` | TEXT NULL | 工作区根路径 | | `environment` | TEXT NULL | 环境名称 | | `duration_ms` | INTEGER NULL | 执行耗时 | | `started_at` | TEXT NOT NULL | 开始时间 | | `finished_at` | TEXT NULL | 结束时间 | | `result_path` | TEXT NULL | 大结果落盘路径 | | `result_json` | TEXT NULL | 小结果 JSON 快照 | | `created_at` | TEXT NOT NULL | 创建时间 | 索引要求:`idx_execution_history_started_at`、`idx_execution_history_file_path`、`idx_execution_history_parent_id` ### `execution_event_index` | 字段 | 类型 | 说明 | | --- | --- | --- | | `id` | INTEGER PRIMARY KEY AUTOINCREMENT | 事件索引 ID | | `execution_id` | TEXT NOT NULL | 执行任务 ID | | `seq` | INTEGER NOT NULL | 事件序号 | | `type` | TEXT NOT NULL | 事件类型 | | `timestamp` | TEXT NOT NULL | 事件时间 | | `payload_path` | TEXT NULL | 大事件载荷落盘路径 | | `payload_json` | TEXT NULL | 小事件载荷 JSON | 索引要求:`idx_execution_event_execution_seq`,并保证同一 `execution_id` 下 `seq` 递增唯一 ### `response_cache_index` | 字段 | 类型 | 说明 | | --- | --- | --- | | `id` | TEXT PRIMARY KEY | 缓存记录 ID | | `workspace_path` | TEXT NULL | 工作区路径 | | `owner_id` | TEXT NOT NULL | 关联执行、事件或历史记录 ID | | `kind` | TEXT NOT NULL | `response-body` / `event-payload` / `history-snapshot` | | `file_path` | TEXT NOT NULL | 缓存文件路径 | | `content_type` | TEXT NULL | 内容类型 | | `size_bytes` | INTEGER NULL | 文件大小 | | `summary_json` | TEXT NULL | 摘要 JSON | | `content_hash` | TEXT NULL | 内容哈希 | | `created_at` | TEXT NOT NULL | 创建时间 | | `expires_at` | TEXT NULL | 过期时间 | 索引要求:`idx_response_cache_owner`、`idx_response_cache_workspace_kind`、`idx_response_cache_expires_at` ### `recent_file_cache` | 字段 | 类型 | 说明 | | --- | --- | --- | | `id` | TEXT PRIMARY KEY | 记录 ID | | `workspace_path` | TEXT NULL | 工作区路径 | | `file_path` | TEXT NOT NULL | 文件路径 | | `cursor_line` | INTEGER NULL | 最近光标行 | | `cursor_column` | INTEGER NULL | 最近光标列 | | `scroll_top` | INTEGER NULL | 最近滚动位置 | | `last_opened_at` | TEXT NOT NULL | 最近打开时间 | 索引要求:`idx_recent_file_cache_last_opened_at` ### `mock_rule_index` | 字段 | 类型 | 说明 | | --- | --- | --- | | `id` | TEXT PRIMARY KEY | Mock 规则 ID | | `workspace_path` | TEXT NOT NULL | 工作区路径 | | `file_path` | TEXT NOT NULL | Mock 规则文件路径 | | `name` | TEXT NOT NULL | 规则名称 | | `enabled` | INTEGER NOT NULL | 是否启用 | | `priority` | INTEGER NOT NULL | 匹配优先级 | | `tags_json` | TEXT NULL | 标签 JSON | | `description` | TEXT NULL | 备注说明 | | `match_summary_json` | TEXT NOT NULL | 匹配条件摘要 JSON | | `response_summary_json` | TEXT NOT NULL | 响应配置摘要 JSON | | `content_hash` | TEXT NOT NULL | 规则文件内容哈希 | | `indexed_at` | TEXT NOT NULL | 最近索引时间 | | `created_at` | TEXT NOT NULL | 创建时间 | | `updated_at` | TEXT NOT NULL | 更新时间 | 索引要求:`idx_mock_rule_index_workspace_enabled`、`idx_mock_rule_index_workspace_priority`、`idx_mock_rule_index_file_path` ### `mock_hit_logs` | 字段 | 类型 | 说明 | | --- | --- | --- | | `id` | TEXT PRIMARY KEY | 命中日志 ID | | `workspace_path` | TEXT NOT NULL | 工作区路径 | | `rule_id` | TEXT NULL | 命中的规则 ID,未命中时为空 | | `matched` | INTEGER NOT NULL | 是否命中 | | `source` | TEXT NOT NULL | 响应来源:`mock-hit`、`mock-miss`、`proxy-hit`、`proxy-error` | | `method` | TEXT NOT NULL | 请求方法 | | `path` | TEXT NOT NULL | 请求路径 | | `status_code` | INTEGER NOT NULL | 响应状态码 | | `duration_ms` | INTEGER NULL | 处理耗时 | | `request_summary_json` | TEXT NULL | 请求摘要 JSON | | `error_summary` | TEXT NULL | 代理或模板错误摘要 | | `requested_at` | TEXT NOT NULL | 请求时间 | 索引要求:`idx_mock_hit_logs_workspace_time`、`idx_mock_hit_logs_rule_id` ### `openapi_source_index` | 字段 | 类型 | 说明 | | --- | --- | --- | | `id` | TEXT PRIMARY KEY | OpenAPI 契约源 ID | | `workspace_path` | TEXT NOT NULL | 工作区路径 | | `name` | TEXT NOT NULL | 契约源名称 | | `source_path` | TEXT NOT NULL | OpenAPI 源文件路径 | | `format` | TEXT NOT NULL | `json` / `yaml` | | `openapi_version` | TEXT NULL | OpenAPI 版本 | | `title` | TEXT NULL | API 标题 | | `version` | TEXT NULL | API 业务版本 | | `operation_count` | INTEGER NOT NULL | operation 数量 | | `content_hash` | TEXT NOT NULL | 源文件内容哈希 | | `last_synced_at` | TEXT NULL | 最近同步时间 | | `indexed_at` | TEXT NOT NULL | 最近索引时间 | 索引要求:`idx_openapi_source_workspace`、`idx_openapi_source_path` ### `openapi_operation_index` | 字段 | 类型 | 说明 | | --- | --- | --- | | `id` | TEXT PRIMARY KEY | operation 索引 ID | | `source_id` | TEXT NOT NULL | OpenAPI 契约源 ID | | `workspace_path` | TEXT NOT NULL | 工作区路径 | | `operation_id` | TEXT NULL | OpenAPI `operationId` | | `method` | TEXT NOT NULL | HTTP 方法 | | `path` | TEXT NOT NULL | OpenAPI 路径 | | `tags_json` | TEXT NULL | 标签 JSON | | `summary` | TEXT NULL | operation 摘要 | | `request_file_path` | TEXT NULL | 生成的 `.http` 文件路径 | | `request_block_id` | TEXT NULL | 生成的请求块 ID | | `mock_rule_id` | TEXT NULL | 生成的 Mock 规则 ID | | `schema_ref` | TEXT NULL | 响应 Schema 引用 | | `content_hash` | TEXT NOT NULL | operation 结构摘要哈希 | | `indexed_at` | TEXT NOT NULL | 最近索引时间 | 索引要求:`idx_openapi_operation_source`、`idx_openapi_operation_workspace_method_path`、`idx_openapi_operation_operation_id` ### `schema_migrations` | 字段 | 类型 | 说明 | | --- | --- | --- | | `version` | TEXT PRIMARY KEY | 迁移版本 | | `name` | TEXT NOT NULL | 迁移名称 | | `applied_at` | TEXT NOT NULL | 执行时间 | | `checksum` | TEXT NULL | 迁移文件校验值 | ### 落盘文件命名规则 * [ ] 工作区环境变量文件默认路径格式:`.http-client/environments.json` * [ ] 工作区项目配置文件默认路径格式:`.http-client/settings.json` * [ ] `.http-client/environments.json`、`.http-client/settings.json`、`.http-client/mocks/**/*.mock.json`、`.http-client/openapi/sources.json` 建议纳入 Git 管理 * [ ] SQLite 缓存数据库、响应缓存、事件缓存、命中日志、诊断包默认位于应用数据目录,不建议纳入 Git 管理 * [ ] 应用可提供推荐 `.gitignore` 片段,覆盖用户显式选择将缓存目录放在工作区内的情况 * [ ] 响应体落盘路径格式:`{appData}/responses/{workspaceHash}/{yyyyMMdd}/{executionId}-{part}.body` * [ ] WebSocket / SSE 大事件载荷落盘路径格式:`{appData}/events/{workspaceHash}/{yyyyMMdd}/{executionId}-{seq}.json` * [ ] Mock 规则文件默认路径格式:`.http-client/mocks/{mockFileName}.mock.json` * [ ] OpenAPI 源映射文件默认路径格式:`.http-client/openapi/sources.json` * [ ] OpenAPI 源文件建议保存在工作区可见目录,例如 `openapi/{sourceName}.yaml` 或 `docs/openapi/{sourceName}.json` * [ ] OpenAPI 生成的 `.http` 请求模板默认路径格式:`generated/openapi/{sourceName}.http` * [ ] OpenAPI 生成的 Mock 规则文件默认路径格式:`.http-client/mocks/openapi/{sourceName}.mock.json` * [ ] OpenAPI Schema 校验映射默认随 `.http` 请求块来源标记保存,不额外生成 SQLite 事实源数据 * [ ] Mock 二进制响应体落盘路径格式:`.http-client/mocks/assets/{mockRuleId}.body` * [ ] `.http-client/mocks/assets/` 仅用于 Mock 规则引用的静态响应体,不用于普通执行响应缓存或压测采样缓存 * [ ] Mock 规则文件需包含 `schemaVersion`、`rules`、`updatedAt` 字段 * [ ] Mock 规则文件加载时需按 `schemaVersion` 进行兼容处理 * [ ] Mock 规则 ID 默认由规则文件相对路径、HTTP 方法、路径匹配表达式和创建时间随机后缀生成,用户修改规则名称不应改变 ID * [ ] 从请求生成 Mock 规则时,若目标文件中已存在同方法同路径规则,默认创建新 ID 并提示可能冲突;用户可选择覆盖已有规则 * [ ] 复制 Mock 规则必须生成新 ID,避免跨文件或同文件重复 ID * [ ] 工作区项目配置文件需保存 Mock 代理回退、Mock 命中日志保留策略、默认环境、历史保留策略等配置 * [ ] Mock 命中日志保留策略需写入工作区项目配置文件,默认值为最近 `10000` 条 / `7d` * [ ] 诊断包导出路径格式:`{appData}/diagnostics/diagnostic-{yyyyMMdd-HHmmss}.zip` * [ ] SQLite 缓存备份文件格式:`{appData}/backups/cache-{schemaVersion}-{yyyyMMdd-HHmmss}.db` 推荐 `.gitignore` 片段: ```gitignore # HTTP Client local cache http-client-cache/ http-client-responses/ http-client-events/ http-client-logs/ http-client-diagnostics/ http-client-backups/ *.db *.db-* ``` ### 工作区 JSON 文件示例 `.http-client/environments.json` 示例: ```json { "schemaVersion": 1, "defaultEnvironment": "dev", "environments": [ { "name": "dev", "variables": { "baseUrl": "https://api.example.com" } } ], "globals": {} } ``` `.http-client/settings.json` 示例: ```json { "schemaVersion": 1, "defaultEnvironment": "dev", "history": { "retentionMaxCount": 1000 }, "mock": { "proxyFallback": { "enabled": false, "upstreamBaseUrl": null }, "hitLog": { "retentionMaxCount": 10000, "retentionDays": 7 } } } ``` `.http-client/mocks/users.mock.json` 示例: ```json { "schemaVersion": 1, "updatedAt": "2026-06-06T10:20:30Z", "rules": [ { "id": "mockrule_users", "name": "Mock list users", "enabled": true, "priority": 100, "match": { "method": "GET", "path": "/users", "pathMode": "exact" }, "response": { "statusCode": 200, "headers": { "Content-Type": "application/json" }, "bodyType": "json", "body": "[{\"id\":1,\"name\":\"demo\"}]", "delayMs": 100, "templateEnabled": false } } ] } ``` `.http-client/openapi/sources.json` 示例: ```json { "schemaVersion": 1, "sources": [ { "id": "openapi_users", "name": "Users API", "sourcePath": "openapi/users.yaml", "format": "yaml", "openapiVersion": "3.1.0", "title": "Users API", "version": "1.0.0", "contentHash": "sha256:openapihash_01HZY7R4T1", "lastSyncedAt": "2026-06-06T10:20:30Z", "targets": { "requestFilePath": "generated/openapi/users.http", "mockFilePath": ".http-client/mocks/openapi/users.mock.json" }, "sync": { "strategy": "skip-local-modified", "generateRequests": true, "generateMocks": true, "enableSchemaValidation": false, "baseUrlVariable": "baseUrl" } } ] } ``` ### 迁移要求 * [ ] SQLite 缓存数据库需维护 `schema_migrations` 表,记录已执行迁移版本 * [ ] 每次版本升级前需备份 SQLite 缓存数据库文件;工作区 JSON 配置文件按普通文件迁移与 Git 管理处理 * [ ] SQLite 缓存数据库迁移失败时需保留原数据库文件,并提示用户查看日志 * [ ] 工作区 JSON 文件迁移需基于 `schemaVersion` 执行,低版本文件可自动迁移,高版本文件默认只读或拒绝写入 * [ ] 工作区 JSON 文件迁移前需在同目录生成备份文件,命名格式为 `{fileName}.bak-{yyyyMMdd-HHmmss}` * [ ] 工作区 JSON 文件迁移失败时不得覆盖原文件,并需提示用户查看迁移错误详情 * [ ] SQLite 缓存迁移失败时允许删除并重建索引;删除前应尽量备份原缓存数据库 ### 测试 Fixture 目录结构 * [ ] 兼容性用例目录:`compat/{category}/{case}.http` * [ ] 工作区夹具目录:`fixtures/workspaces/{caseName}/` * [ ] API 示例快照目录:`fixtures/api-snapshots/{apiName}.json` * [ ] 解析器 golden 快照目录:`fixtures/parser-golden/{caseName}.json` * [ ] Mock 规则夹具目录:`fixtures/workspaces/{caseName}/.http-client/mocks/*.mock.json` * [ ] OpenAPI 契约夹具目录:`fixtures/workspaces/{caseName}/openapi/*.yaml` * [ ] OpenAPI 源映射夹具目录:`fixtures/workspaces/{caseName}/.http-client/openapi/sources.json` * [ ] OpenAPI 生成请求夹具目录:`fixtures/workspaces/{caseName}/generated/openapi/*.http` * [ ] 测试快照需纳入版本管理,运行时生成的响应缓存、日志、SQLite 缓存不得写入 fixture 目录 ## MVP 任务拆分 ### 后端 MVP 任务 * [ ] `MVP-BE-01`:完成本地服务启动、端口探测、单实例复用、静态资源托管和运行时元信息文件 * [ ] `MVP-BE-02`:完成 `workspace` 与 `filestore`,支持工作区打开、路径解析、文件读取、原子保存、`contentHash` 和外部变更检测 * [ ] `MVP-BE-03`:完成 `.http` / `.rest` MVP 解析器,输出稳定 AST、请求块列表、请求命名、注释、错误位置和 parser golden 快照 * [ ] `MVP-BE-04`:完成环境变量文件 `.http-client/environments.json` 的读取、保存、默认环境、变量优先级和未定义变量错误 * [ ] `MVP-BE-05`:完成 REST API envelope、错误码映射、分页模型、内部 OpenAPI 契约源和前端类型生成输入 * [ ] `MVP-BE-06`:完成 `eventbus` MVP,支持事件发布、WebSocket 订阅、`seq`、最终事件和页面刷新后的最终结果快照补拉 * [ ] `MVP-BE-07`:完成 `Execution` MVP 状态机,支持普通 HTTP 请求执行、取消、超时、响应 meta/body、结果固化 * [ ] `MVP-BE-08`:完成 JavaScript 前置脚本、后置脚本、基础断言、脚本日志和脚本超时 * [ ] `MVP-BE-09`:完成 SQLite `execution_history_index`、`execution_event_index`、`response_cache_index`、`recent_file_cache` 的初始化、写入和重建入口 * [ ] `MVP-BE-10`:完成后端测试基线,包括 parser golden tests、execution integration tests、API handler tests、script runtime tests ### 前端 MVP 任务 * [ ] `MVP-FE-01`:完成应用 shell、三栏布局、路由、全局状态和基础错误提示 * [ ] `MVP-FE-02`:完成统一 API client、WebSocket event client、错误 envelope 处理、事件去重和断线重连 * [ ] `MVP-FE-03`:完成文件树、最近文件、文件打开、文件保存、外部变更提示和 Monaco Editor 集成 * [ ] `MVP-FE-04`:完成当前请求定位、请求块高亮、执行当前请求、取消执行和执行状态展示 * [ ] `MVP-FE-05`:完成环境切换、变量预览、环境列表、环境变量编辑和默认环境设置 * [ ] `MVP-FE-06`:完成响应查看器 MVP,支持 Body、Headers、Cookies、Timeline、Logs、Raw / Pretty 展示和大响应截断提示 * [ ] `MVP-FE-07`:完成历史列表、历史详情、重新执行、打开源文件和定位请求块 * [ ] `MVP-FE-08`:完成托盘相关前端入口,包括打开页面、退出服务、打开数据目录的状态展示 * [ ] `MVP-FE-09`:完成前端测试基线,包括编辑器、响应区、环境管理、历史详情和主流程 E2E ### MVP 纵向验收切片 * [ ] `MVP-VS-01`:打开工作区 -> 扫描 `.http` 文件 -> 展示请求列表 -> 定位当前请求 * [ ] `MVP-VS-02`:编辑请求 -> 保存文件 -> 执行当前请求 -> WebSocket 增量展示响应 -> 固化历史 * [ ] `MVP-VS-03`:创建环境 -> 切换环境 -> 变量预览刷新 -> 使用环境变量执行请求 * [ ] `MVP-VS-04`:执行带前置脚本、后置脚本和断言的请求 -> 展示脚本日志和断言结果 * [ ] `MVP-VS-05`:取消长耗时请求 -> 状态进入 `cancelled` -> 历史中保留取消摘要 * [ ] `MVP-VS-06`:页面刷新或 WebSocket 断开重连 -> 根据 `executionId` 恢复最终状态或结果快照 * [ ] `MVP-VS-07`:外部修改 `.http` 或环境文件 -> 应用提示变更 -> 用户重新加载后索引更新 ## 实施步骤 ### 阶段 0:项目骨架 * [ ] 初始化 Go module 与后端目录结构 * [ ] 初始化 Vue 3 + TypeScript + Vite 前端项目 * [ ] 建立前后端开发命令、构建命令、测试命令 * [ ] 实现本地服务启动、默认端口、端口探测、静态资源托管 * [ ] 建立 SQLite 索引/缓存初始化、`schema_migrations`、数据目录结构 ### 阶段 1:MVP 后端 * [ ] 实现 `.http` / `.rest` 基础解析、多请求块、请求命名、注释、错误定位 * [ ] 实现变量解析、MVP 变量优先级、未定义变量错误 * [ ] 实现本地工作区文件读取、保存、最近文件、外部变更检测 * [ ] 实现 `Execution` 状态机、REST 控制面、WebSocket 事件通道 * [ ] 实现单请求执行、取消、超时、响应结果固化 * [ ] 实现请求历史索引、响应缓存索引、环境变量文件存储、项目配置文件存储 * [ ] 实现 JavaScript 前置脚本、后置脚本、基础断言 ### 阶段 2:MVP 前端 * [ ] 实现主界面三栏布局、文件树、Monaco Editor、响应区标签页 * [ ] 实现当前请求定位、当前请求高亮、执行当前请求 * [ ] 实现变量预览、环境切换、错误行列定位 * [ ] 实现响应 Body / Headers / Cookies / Timeline / Logs 展示 * [ ] 实现请求取消、执行状态展示、WebSocket 事件增量渲染 * [ ] 实现历史列表、历史详情、重新执行 * [ ] 实现托盘打开页面、退出服务、打开数据目录 ### 阶段 3:MVP 验收 * [ ] 建立 MVP 兼容用例集并接入回归测试 * [ ] 完成 parser golden tests、executor integration tests、API handler tests * [ ] 完成前端核心组件测试与主流程 E2E 测试 * [ ] 验收文件打开、请求执行、取消、历史回看、环境切换、状态恢复主流程 ### 阶段 4:产品目标版本增强 * [ ] 实现 Form URL Encoded、Multipart、二进制 Body、外部文件引用 * [ ] 实现 Cookie 管理、重定向链、代理、SSL/TLS、客户端证书 * [ ] 实现批量执行、链式执行、父子任务历史展示 * [ ] 实现 SSE 与 WebSocket 会话视图、消息发送、摘要存储 * [ ] 实现轻量压测执行、实时统计、保护阈值、历史报告 * [ ] 实现本地 Mock Server、Mock 规则管理、规则优先级、代理回退、命中日志、规则文件保存/重载与从请求/响应生成 Mock * [ ] 实现 curl 导出、Postman collection 导入、OpenAPI 导入与同步 * [ ] 实现 OpenAPI diff、生成 Mock 骨架和响应 Schema 校验 * [ ] 完善兼容矩阵完整用例集与产品目标版本回归测试 ### 阶段 5:打包发布 * [ ] 完成 Windows / macOS / Linux 打包产物 * [ ] 完成 SQLite 缓存数据库迁移、工作区 JSON schema 迁移、升级备份、失败回滚验证 * [ ] 完成日志目录、诊断包导出、异常退出提示 * [ ] 完成平台差异清单与发布说明 ## .http 文件语法示例 ``` ### GET 请求示例 GET https://api.example.com/users Accept: application/json ### ### POST 请求示例 POST https://api.example.com/users Content-Type: application/json Authorization: Bearer {{token}} { "name": "John Doe", "email": "john@example.com" } ### ### PUT 请求示例 PUT https://api.example.com/users/1 Content-Type: application/json { "name": "Jane Doe" } ### ### 签名请求示例 GET https://api.example.com/orders Accept: application/json < {% const secret = vars.get("secret"); const timestamp = Date.now().toString(); const req = request.get(); const payload = `${req.method}\n${req.url}\n${timestamp}`; const signature = crypto.hmacSha256Hex(secret, payload); request.setHeader("X-Timestamp", timestamp); request.setHeader("X-Signature", signature); %} ``` ## 系统托盘功能要求 * 显示应用图标 * 单击打开应用页面 * 右键菜单包含: * 打开应用页面 * 打开数据目录 * 分隔线 * 退出