electron-anyproxy源码解析(四):recorder基于nedb的请求录制与缓存架构设计

发布时间:2026/10/9 18:16:57

electron-anyproxy源码解析(四):recorder基于nedb的请求录制与缓存架构设计 electron-anyproxy源码解析四recorder基于nedb的请求录制与缓存架构设计【免费下载链接】electron-anyproxy A http/https proxy client, using to analyze and mock.项目地址: https://gitcode.com/gh_mirrors/el/electron-anyproxyelectron-anyproxy 是一款基于 Electron 的 http/https 代理客户端核心能力是抓包分析与接口 Mock。本篇 electron-anyproxy源码解析继续深入其内部实现聚焦请求录制模块 recorder它如何在内存、nedb 数据库与文件系统三者之间分配职责如何做到「元数据入库、响应体落盘」的缓存架构设计以及如何通过事件机制把录制结果实时推送到前端界面。理解了这套架构你就掌握了整个代理工具数据链路的地基。一、recorder 模块的定位整个代理工具的「数据中枢」在 electron-anyproxy 中recorder 是记录一切的模块它记录每一次请求的 URL、Host、Method、请求头、响应头、状态码、耗时以及完整的请求/响应体。它并不直接处理网络 IO而是作为被动接收者由请求处理链路主动喂数据。recorder 实例在 proxy.js 的 ProxyServer 构造器中创建this.recorder new Recorder(); global.recorder this.recorder;创建后它被注入 RequestHandlerlib/requestHandler.js和 webInterfacelib/webInterface.js成为请求处理与前端展示之间的桥梁。可以说recorder 是代理工具的「数据中枢」。二、缓存架构设计内存自增 ID nedb 数据库 文件系统三层结构这是整个模块最值得学习的设计。recorder 没有把所有数据一股脑塞进数据库而是做了清晰的分层数据存储位置设计原因自增 ID内存变量globalId生成唯一主键避免依赖数据库自增请求/响应元数据nedb 数据库文件结构化查询、排序、分页响应体内容独立文件res_body_{id}大体积二进制不污染数据库按需读取1. 随机缓存目录每次启动都是全新的快照recorder 初始化时会生成一个随机缓存目录lib/recorder.jsconst CACHE_DIR_PREFIX cache_r; const DB_FILE_NAME anyproxy_db; function getCacheDir() { const rand Math.floor(Math.random() * 1000000); const cachePath path.join(proxyUtil.getAnyProxyPath(cache), ./ CACHE_DIR_PREFIX rand); fs.mkdirSync(cachePath); return cachePath; }目录位于~/.anyproxy/cache/cache_r{随机数}下。随机后缀意味着每次启动代理都是全新的录制快照互不干扰也简化了清理逻辑。2. nedb 数据库零配置的嵌入式文档数据库recorder 使用 nedb 作为存储引擎。nedb 是纯 JavaScript 实现的嵌入式 NoSQL 数据库API 与 MongoDB 高度相似非常适合 Electron 这类需要随应用分发、又不想引入重量级数据库服务的场景db new Datastore({ filename: dbFilePath, autoload: true }); db.persistence.setAutocompactionInterval(5001);两个细节值得注意autoload: true让数据库打开即用setAutocompactionInterval(5001)每 5 秒自动压缩一次数据文件。nedb 采用 append-only 写入频繁更新会产生大量冗余记录自动压缩能显著减小文件体积。如果磁盘文件加载失败比如权限问题代码会优雅降级为纯内存数据库保证代理功能不中断这种容错思路值得借鉴。3. 响应体落盘body-map 设计响应体可能包含大图片、大文件没有存入数据库而是单独写成文件const BODY_FILE_PRFIX res_body_; self.updateRecordBody function (id, info) { if (!id || !info.resBody) return; const bodyFile path.join(cachePath, BODY_FILE_PRFIX id); fs.writeFile(bodyFile, info.resBody); };数据库里只保存_id响应体通过res_body_{id}文件按需读取。这种「元数据与内容分离」的缓存架构设计避免了数据库膨胀也让大响应体的读取不会阻塞录制流程。三、请求录制核心流程appendRecord 与 updateRecord 的前后呼应录制不是一个动作而是一对动作由 lib/requestHandler.js 在请求处理的不同阶段触发请求到达时调用recorder.appendRecord(resourceInfo)分配自增 ID插入初始记录并立即通过事件推送前端用户能马上看到「请求已发出」响应返回后填充状态码、响应头、响应体、耗时等字段调用recorder.updateRecord(resourceInfoId, resourceInfo)更新同一条记录。这两个方法内部都调用了normalizeInfo把原始信息规整为统一的记录结构singleRecord._id id; singleRecord.url info.url; singleRecord.host info.host; singleRecord.method info.method; singleRecord.reqHeader info.req.headers; singleRecord.startTime info.startTime; singleRecord.statusCode info.statusCode; singleRecord.resHeader info.resHeader; singleRecord.duration info.endTime - info.startTime;其中duration耗时由 endTime 减去 startTime 计算得出为前端展示接口耗时提供了直接数据。四、响应体解码字符集识别与类型判定的巧妙处理响应体拿到手后不能直接展示recorder 提供了getDecodedBody方法完成两件事字符集解码遍历响应头 JSON 字符串正则匹配charset若服务端不是 UTF-8 编码则用 iconv-lite 转码内容类型判定根据content-type区分 JSON、图片和普通文本图片以 Buffer 形式返回便于前端直接渲染。对应前端接口位于 lib/webInterface.js/fetchBody?idxx返回解码后的内容rawtrue则直接输出原始二进制如图片。五、查询接口设计满足列表、分页与详情的全部场景recorder 暴露了四个查询方法覆盖前端所有数据需求getSummaryList(cb)全量查询用于统计getRecords(idStart, limit, cb)按_id升序排序并分页配合 Web 界面「加载更多」的场景例如 webInterface 中一次取 10000 条lib/webInterface.js 的/latestLog接口getSingleRecord(id, cb)按主键查询单条详情getBody(id, cb)/getDecodedBody(id, cb)读取响应体。排序、limit 都直接在 nedb 查询中完成无需在 JS 层做二次处理代码非常精简。六、事件驱动EventEmitter 与 WebSocket 的实时推送链路recorder 继承了events.EventEmitter这是它连接前端的关键设计。emitUpdate在每次 append 或 update 后触发update事件而 lib/wsServer.js 订阅了这个事件recorder.on(update, (data) { sendMultipleMessage(data); });消息不会一条条立刻发出而是先进入messageQueue队列由 50ms 的定时器批量打包广播前端通过 WebSocket 一次性收到多条更新大幅降低推送频率、提升渲染性能。这正是客户端 network.vue 中请求列表实时滚动的数据来源。七、缓存清理机制关闭即清空ProxyServer 的close()方法会调用recorder.clear()通过递归删除缓存目录实现一键清空lib/util.js 的deleteFolderContentsRecursive。因为缓存目录是随机命名的独立快照删除时无需担心误伤其他数据这也是随机目录设计带来的另一大红利。八、总结recorder 架构设计的三个启示回顾整个 lib/recorder.js这套请求录制与缓存架构设计给我们带来三点启发职责分层元数据入库、内容落盘、ID 自增放内存各司其职互不拖累容错降级数据库加载失败自动切内存模式保证代理主流程不受影响事件解耦录制、推送、展示通过事件机制解耦新增消费方只需监听update事件无需改动录制核心。下一篇 electron-anyproxy源码解析将继续剖析 rule 规则引擎与 Mock 机制看这些被录制的数据如何反过来支撑接口模拟与篡改敬请期待。【免费下载链接】electron-anyproxy A http/https proxy client, using to analyze and mock.项目地址: https://gitcode.com/gh_mirrors/el/electron-anyproxy创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
延伸阅读

更多相关文章

2026/10/7 22:09:09

parsec-vdd 实战:在 Windows 上凭空点亮 16 块 4K 虚拟屏

parsec-vdd 实战:在 Windows 上凭空点亮 16 块 4K 虚拟屏 【免费下载链接】parsec-vdd ✨ Perfect virtual display for game streaming 项目地址: https://gitcode.com/gh_mirrors/pa/parsec-vdd 远程客户端一连上就愣住了:分辨率 1024768&#…

2026/10/6 18:35:15

Rpisurv路线图解读:继任者OpenSurv带来哪些新能力?

Rpisurv路线图解读:继任者OpenSurv带来哪些新能力? 【免费下载链接】rpisurv Raspberry Pi surveillance 项目地址: https://gitcode.com/gh_mirrors/rp/rpisurv Rpisurv是一款免费开源的树莓派监控软件(Raspberry Pi surveillance&am…

2026/10/10 4:15:12

零代码API服务:用SQL直接定义HTTP接口的实践指南

简介:一套面向数据驱动型业务场景的零代码API开发方案,核心思路是让开发者仅编写SQL查询语句,即可自动生成可被HTTP调用的API服务,适合BI报表、数据可视化大屏等后端接口快速搭建,也降低了非程序员参与API设计的门槛。…

2026/10/10 4:15:12

claude-mem:为Claude CLI打造持久化记忆,告别跨会话上下文丢失

1. 一个让人上火的重复劳动,和它的解药先说个我自己的场景。我平时用 Claude 的 CLI 工具写代码、做技术调研,尤其是维护几个跨端的项目时,几乎每天都要在同一类上下文里反复确认:"上次咱们定的模块边界是什么来着&#xff1…

2026/10/10 4:15:12

PE+ISO双模启动U盘:系统修复与重装一体化实战指南

1. 这不是普通U盘,而是一把“系统手术刀”:PEISO一体化启动盘的本质与价值你手头那张标着“Windows安装盘”的U盘,大概率只是个半成品。它能装系统,但装完蓝屏了怎么办?驱动不认、分区错乱、引导损坏、硬盘突然变RAW—…

2026/10/10 4:15:12

C++状态模式工程实战:从状态机设计到std::variant高级应用

状态模式大概是设计模式里最容易被低估的一个。大多数教程只拿灯开关、电风扇转速来举例,类图画得挺漂亮,代码写出来也就几十行。但等你真的在C项目里把状态模式往生产环境一放,很快就会碰上一堆教科书没写过的问题:状态太多导致类爆炸、转换逻辑散落在各个状态类里、状态对象创…

2026/10/10 4:15:12

Joern + cpgqls-client + Python 自动化代码安全扫描实战

最近在梳理团队内部的代码安全扫描流程,终于把 Joern 服务器、cpgqls-client 和 Python 编程这条链路彻底跑通了。先说结论:这套组合非常适合做自动化漏洞挖掘和批量代码审计,尤其是需要把扫描结果沉淀成结构化数据,再喂给后续的工…

2026/10/10 4:10:12

Antigravity上线Opus 5.5与Sonnet 5.5:新模型能力、权限分层与调用指南

Antigravity 悄悄把 Opus 5.5 和 Sonnet 5.5 挂上去了,我是在一次例行检查模型列表时发现的。当时第一反应是“终于来了”,第二反应是“怎么我的账号还没解锁”。在开发者社区里转了一圈,发现大家的情况基本一样:模型确实上线了&a…

2026/10/8 10:03:18

Jev+Agent接管浏览器:browser-use实战与jev-ultrafast性能优化

1. 从“Jev”说起:为什么我要把Agent接进浏览器“Jev”这个词最近在圈子里出现的频率越来越高,很多人第一次听到会以为是某个新模型的名字,其实它更像是一种思路——把Jev模型的能力当作底座,通过Agent的方式去接管浏览器&#xf…

2026/10/9 20:15:56

多智能体集群实战:DeepAgents编排、MCP与A2A协议及Skills体系

1. 从"单兵作战"到"集群协同":多智能体编排到底在解决什么问题如果你最近在折腾 Agent 相关的东西,大概率会有一种感觉:单个 Agent 能做的事情,其实很快就摸到天花板了。你给它一个提示词,挂几个工…

2026/10/8 6:05:44

无源低通滤波器设计实战:从RC到LC,手把手教你避开那些坑

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 0:04:53

从逻辑门到计算机:数字电路核心原理与全加器搭建实战

如果你拆过一台旧电脑的主板,盯着那些黑乎乎的小芯片看上一会儿,可能会冒出同一个疑问:这堆引脚密集的元件,到底是怎么“变”出那么复杂的应用的?答案并不在某个神秘的部件里,而是在所有芯片内部都在反复使…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑