44、【Agent】【OpenCode】本地代理分析(八)
【声明】本博客所有内容均为个人业余时间创作,所述技术案例均来自公开开源项目(如Github,Apache基金会),不涉及任何企业机密或未公开技术,如有侵权请联系删除
背景
上篇 blog
【Agent】【OpenCode】本地代理分析(七)
提到了一个关键点,代理收到 Open构建了请求对象,然后发送请求内容后,代理就 return 退出了,解释了这里虽然 https.request 本身同步返回请求对象,但整个 IO 是异步的,涉及到 JavaScript 异步 + 闭包 + 流式处理中的核心机制:proxyReq.end 只是发出请求,并不代表请求完成,Node.js 的事件循环模块会持续监听网络事件,当目标服务器 DashScope 返回响应头时,Node.js 会自动调用回调函数 (proxyRes) => {...},即使外层函数已经 return,回调依然能安全访问 res 等变量,这就是闭包(Closure)在起作用,而 proxyRes 是由系统在回调触发时新创建的对象,下面继续分析
OpenCode
再解释下这里的接收回调函数

首先是入参 proxyRes,这不是用户自定义的局部变量,而是 Node.js 在触发接收回调时,动态创建的参数,每次收到一个响应,系统都会新建一个 proxyRes 对象传进来,也就是说,这个对象在接收回调开始时才被定义生成
另外是内存安全的问题
- 之前提到过,在运行时,JavaScript 的引擎会发现,内部接收回调函数使用到了外部的变量
res,于是引擎会保留对res变量的引用,即使外层函数(OpenCode 客户端对目标服务器的请求)返回结束,只要还有回调函数(指的是这里的接收回调函数)可能用到它,res变量就不会被垃圾回收,这是 JavaScript 闭包的标准行为 - 在这里,
res(客户端响应对象)的生命周期由 Node.js 管理,一旦proxyRes.pipe(res)完成(之前说过,pipe会自动end)或出错,所有引用会自然解除,另外,当 HTTP 连接关闭时,res也会被自动清理,所以也不会出现内存泄漏
最后总结下这里本地代理的关键点
- 客户端 OpenCode 的请求函数 return 返回后,其定义的接收回调函数还能正常运行,Node.js 的事件循环模块会触发这个接收 callback 的调用
- 客户端 OpenCode 的请求函数 return 返回后,其入参
res变量还会继续存在,由闭包机制保持引用,以便接收回调函数实现透传 proxyRes是接收 callback 被调用时新建的,不是用户自定义的变量- 没有内存泄漏问题,Node.js 会自动管理 HTTPS 连接的生命周期,这也是 Node.js 流式代理的标准做法
正是这种非阻塞式,事件驱动的模型,可以让 Node.s 能够高效处理成千上万的并发 AI 请求
再贴一次本地代理的实现
// dashscope-proxy.js
const http = require('http');
const https = require('https');
const server = http.createServer((req, res) => {
console.log(`📥 Received ${req.method} ${req.url}`);
if (req.method === 'POST' && req.url === '/v1/chat/completions') {
let body = '';
req.on('data', chunk => body += chunk);
req.on('end', () => {
// 从原始请求中获取 Authorization 头
const authHeader = req.headers['authorization'] || '';
const options = {
hostname: 'dashscope.aliyuncs.com',
port: 443,
path: '/compatible-mode/v1/chat/completions',
method: 'POST',
headers: {
'Authorization': authHeader, // 直接透传
'Content-Type': 'application/json',
'Content-Length': Buffer.byteLength(body)
}
};
const proxyReq = https.request(options, (proxyRes) => {
res.writeHead(proxyRes.statusCode, proxyRes.headers);
proxyRes.pipe(res); // 自动处理流式/非流式 + 自动 end()
});
proxyReq.on('error', (e) => {
console.error('Proxy error:', e.message);
res.writeHead(502);
res.end('Bad Gateway');
});
proxyReq.write(body);
proxyReq.end();
});
return;
}
res.writeHead(404);
res.end('Not Found');
});
server.listen(2048, '127.0.0.1', () => {
console.log('✅ DashScope proxy with full OpenCode & Ollama compatibility running on http://127.0.0.1:2048');
});
OK,本地代理分析完后,把项目里 opencode.json 的 api 参数改一下,改成创建的本地代理 URL(这里设置的是 2048 端口号)

接着在终端输入
node dashscope-proxy.js
启动代理程序,可以看到端口已被代理程序占用
新建另一个终端,打开 OpenCode,输入
你是哪个模型?
可以看到 OpenCode 客户端的响应

同时本地代理进行了两次请求的转发

至于这里为什么会有两次请求,后面 blog 会进行分析
OK,本篇先到这里,如有疑问,欢迎评论区留言讨论,祝各位功力大涨,技术更上一层楼!!!更多内容见下篇 blog
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐

所有评论(0)