好的,这是一份经过整理和条理化的复盘报告,涵盖了您提供的所有内容。


项目开发复盘报告:题库适配器与平台迁移

本文档旨在系统地复盘“为 tikuAdapter 新增适配端点”任务从初期开发、环境配置、数据兼容性处理,直至最终平台迁移与自动化部署的完整过程。报告详细记录了关键任务、遇到的问题、解决方案及宝贵的经验教训。

I. 核心API端点开发与初期问题解决

1.1 任务目标

创建一个新的 API 端点 /tikuAdapter,该端点能够接收特定格式请求,调用外部题库 API (api.tikuhai.com),并将返回数据转换为 tikuAdapter 所需的 JSON 格式。

1.2 已完成工作

  • 新增 /tikuAdapter 端点:在 src/app.js 中成功添加了路由和 handleTikuAdapterSearch 处理函数。
  • 实现数据格式转换:在 handleTikuAdapterSearch 中编写核心逻辑,将 api.tikuhai.com 的响应重组,包括保留 questionoptions,并动态生成 answerKeyanswerIndexanswerKeyTextanswerText 等字段。

1.3 遇到的问题及解决方案

问题一:服务器连接重置

  • 现象: curl 测试时收到 (56) Recv failure: Connection was reset 错误。
  • 分析: 服务器处理请求时意外终止或崩溃。
  • 解决方案: 检查 request.log 日志文件,定位导致崩溃的具体异常。

问题二:处理 options 字段时的类型错误

  • 现象: 日志显示 TypeError: Cannot read properties of undefined (reading 'indexOf')
  • 分析: 当客户端请求 JSON 不含 options 字段时,options 变量为 undefined,导致后续调用 indexOf 失败。
  • 解决方案: 增加防御性编程:const options = data.options || [];,确保 options 始终为数组,即使请求中未提供。

II. 开发环境配置与效率提升

2.1 原始需求:实现开发环境下的代码热重载

  • 目标: 修改后端代码后服务能自动重启,提升开发效率。
  • 解决方案: 采用 Node.js v18.11.0+ 内置的 --watch 标志。
  • 优势: 无需额外依赖(如 nodemon),官方支持,性能更佳。
  • 实施: 修改 package.json,添加 "dev": "node --watch src/app.js" 命令,通过 npm run dev 启动。

2.2 衍生问题:端口被占用 (EADDRINUSE)

  • 现象: 启动开发服务时抛出 Error: listen EADDRINUSE: address already in use :::3000 错误。
  • 分析: 端口 3000 被未正常关闭的原服务进程占用。
  • 解决方案:
    1. 定位进程: 使用 netstat -aon | findstr ":3000" 查找占用端口的进程ID (PID)。
    2. 终止进程: 使用 taskkill /PID [PID] /F 强制结束该进程,释放端口。

III. 请求数据处理与外部API兼容性增强

3.1 背景

在调试过程中,目标是正确解析前端请求体,并确保转发给 api.tikuhai.com 的数据格式正确。

3.2 问题一:无法正确解析 text/plain 请求体

  • 现象: curl 发送 Content-Type: text/plain 请求时,服务器日志显示 前端传入值: {}
  • 分析: Express 的 express.json() 中间件默认只处理 application/json 请求,忽略 text/plain
  • 解决方案:
    1. src/app.js 中添加 app.use(express.text()); 中间件。
    2. handleSearch 函数中增加逻辑,当 req.body 为字符串时,使用 JSON.parse() 转换为对象。

3.3 问题二:因 options 字段类型不匹配导致 500 错误

  • 现象: 特定用例 (options 字段为空字符串) 转发到 api.tikuhai.com 后返回 500 错误。
  • 分析: 客户端传入 {"options": ""} 会覆盖 config.js 中的默认空数组 []。后端服务预期 options 为数组,收到字符串导致处理失败。
  • 解决方案: 在数据合并后、发送请求前,增加精准修正逻辑:
    1
    2
    3
    
    if (forwardData.options === '') {
      forwardData.options = [];
    }
    
    此方案确保了 options 字段在转发前始终为数组格式。

3.4 与 OCS 脚本对接及功能增强

问题一:修复 handler 答案解析逻辑

  • 问题: ocs-tiku-hi-adapter.json 配置中 handler 函数返回值格式不符 OCS 规范。
  • 解决方案: 修改 handler 函数返回 [题目, 答案] 格式数组,并增加对多选题答案(# 分隔)和接口错误信息([错误信息, undefined])的处理。

问题二:解决跨域请求 (CORS) 失败问题

  • 问题: 浏览器从 https://i.chaoxing.com 向本地服务发起请求时,因 CORS 策略导致 OPTIONS 预检请求返回 403 Forbidden
  • 解决方案:
    1. 安装 cors npm 包。
    2. src/app.js 中引入并配置 cors 中间件,明确允许来自 https://i.chaoxing.com 的跨域请求。

问题三:增加接口 key 验证的调试开关

  • 目标: 方便开发调试,临时关闭 key: '114514' 验证。
  • 解决方案: 在 src/config.js 中增加 disableKeyCheck 布尔配置项,并在 src/app.js 中根据其值决定是否执行 key 验证逻辑。

问题四:规范化 options 参数处理

  • 问题: 填空题等无选项请求缺少 options 字段,需默认值确保转发格式正确。
  • 解决方案:
    1. src/config.js 中为 options 设置默认值 []
    2. src/app.js 中增加逻辑:若 options 存在且为字符串,则按 \n 分割为数组;若不存在,则使用配置中的默认空数组。确保转发给 api.tikuhai.comoptions 始终为数组。

IV. 平台迁移与自动化部署 (Deno Deploy)

4.1 目标

将基于 Node.js 和 Express 的现有项目迁移到 Deno 平台,并配置通过 CI/CD 自动部署到 Deno Deploy。

4.2 已解决的核心问题

问题一:运行时环境不兼容

  • 问题: 原始项目基于 Node.js、Express 和 CommonJS 模块,与 Deno 的原生运行时和 ES 模块系统不兼容。
  • 解决方案: 创建新入口文件 deno_app.js,使用 Deno 内置的 Deno.serve 替换 Express 服务器,并手动将所有 require 转换为 import

问题二:依赖管理与移除 node_modules

  • 问题: 项目依赖 axios@faker-js/faker 通过 npm 安装在 node_modules 目录,Deno Deploy 不支持。
  • 解决方案:
    • axios 替换为 Deno 内置的 fetch API。
    • @faker-js/faker 通过 Deno 官方第三方模块库 deno.land/x 找到替代模块,直接通过 URL 导入 (https://deno.land/x/faker@v1.0.3/mod.ts)。

问题三:文件系统写入限制

  • 问题: 原始应用将日志写入本地 request.log,Deno Deploy 生产环境文件系统只读。
  • 解决方案: 将日志记录逻辑从写入文件修改为使用 console.log 输出到标准输出。Deno Deploy 会自动捕获这些控制台日志并在线上仪表盘中展示。

问题四:自动化部署流程缺失

  • 问题: 项目没有自动化部署流程,需手动操作。
  • 解决方案: 创建 GitHub Actions 配置文件 .github/workflows/deploy.yml,配置 CI/CD 工作流。该工作流在代码推送到 main 分支时自动触发,使用 deployctl 工具将 deno_app.js 应用部署到 Deno Deploy。

4.3 最终成果

  • 一个完全兼容 Deno 运行时的独立应用文件 deno_app.js
  • 一个可重复、可靠的自动化部署流程,定义在 .github/workflows/deploy.yml 中。
  • 项目现在已准备就绪,可通过 GitHub Actions 或本地命令行工具 deployctl 轻松部署到 Deno Deploy 的全球边缘网络。

V. 总结与经验教训

本次项目开发与复盘涵盖了从 API 设计、前端对接、后端数据兼容性、开发环境优化,到最终的平台迁移和自动化部署的多个环节。

主要成就

  1. 成功开发并部署了 tikuAdapter API 端点,实现了与外部题库的对接及数据转换。
  2. 构建了高效的开发环境,通过 Node.js --watch 和端口占用问题解决,显著提升了开发效率。
  3. 增强了服务器对多种 Content-Type 请求的解析能力,并通过防御性编程和特定边缘用例处理,极大提升了数据处理的健壮性和兼容性。
  4. 成功将项目从 Node.js 环境平滑迁移至 Deno 平台,并建立了完善的 CI/CD 自动化部署流程。

经验教训

  • Content-Type 的重要性:在处理HTTP请求时,严格理解和遵守 Content-Type 至关重要。例如,Express 的中间件默认只处理 application/json,对于 text/plain 或其他类型需要显式配置。这是一个深刻的教训。
  • 防御性编程:在处理可能来自用户或外部接口的数据时,应始终预设数据可能不完整或格式不正确,通过添加空值判断、默认值或类型转换来避免运行时错误,提高代码健壮性。
  • 开发工具的利用:善用平台提供的原生开发工具(如 Node.js --watch)可以减少对第三方依赖的引入,保持项目轻量。
  • 系统诊断能力:掌握 netstattaskkill 等命令行工具对于诊断和解决环境问题(如端口占用)至关重要。
  • 平台特性考量:在进行平台迁移时,必须全面了解目标平台的运行时特性(如模块系统、文件系统限制、网络API),并相应地调整代码和依赖管理。
  • CI/CD 自动化:早期规划并实现自动化部署流程,可以大幅减少手动部署的错误,并提高发布效率和一致性。

本次复盘为未来的项目开发积累了宝贵的经验,使团队在处理复杂系统集成和部署问题时更加成熟和高效。