docs/archives/122-docker-api-proxy/implementation.md
前端应用 → nginx (80) → Node Proxy (3001) → 外部LLM API
基于Docker受信环境假设,采用简化优先的设计原则:
问题:nginx动态代理需要复杂的DNS解析和变量处理 解决方案:采用nginx本地转发 + Node.js代理的简化架构
location /api/proxy {
proxy_pass http://127.0.0.1:3001;
proxy_http_version 1.1;
}
问题:SSE流式响应需要实时透传,不能缓冲 解决方案:
proxy_buffering off、X-Accel-Buffering noReadable.fromWeb()正确处理流问题:nginx和Node.js同时设置CORS头导致重复 解决方案:统一由Node.js处理CORS,nginx不设置
问题:LLM流式请求可能需要很长时间,统一超时不合理 解决方案:差异化超时策略
创建Node.js代理服务
配置nginx转发
/api/proxy和/api/stream路径Docker集成
流式响应优化
Readable.fromWeb()处理流前端UI集成
数据持久化
增强错误处理
LLM服务集成
端到端验证
// 基础代理测试
GET /api/proxy?url=https://httpbin.org/get
期望:200状态码,正确的JSON响应
// 错误处理测试
GET /api/proxy?url=https://nonexistent-domain.com
期望:502状态码,友好错误消息
// 流式响应测试
GET /api/stream?url=https://httpbin.org/stream/5
期望:实时流式数据,无缓冲延迟
// 零依赖实现,只使用内置模块
const http = require('http');
const { Readable } = require('stream');
// 流式响应处理
if (upstreamRes.headers['content-type']?.includes('text/event-stream')) {
const stream = Readable.fromWeb(upstreamRes.body);
stream.pipe(res);
}
// 智能错误处理
const handleError = (error, res, requestId) => {
if (error.code === 'ENOTFOUND') {
return sendError(res, 502, 'DNS resolution failed', requestId);
}
if (error.code === 'ECONNREFUSED') {
return sendError(res, 502, 'Connection refused', requestId);
}
return sendError(res, 500, 'Internal server error', requestId);
};
# 基础代理配置
location /api/proxy {
proxy_pass http://127.0.0.1:3001;
proxy_http_version 1.1;
}
# 流式响应配置
location /api/stream {
proxy_pass http://127.0.0.1:3001;
proxy_buffering off;
proxy_request_buffering off;
add_header X-Accel-Buffering no always;
}
export const checkDockerApiAvailability = async (): Promise<boolean> => {
try {
const response = await fetch('/api/docker-status');
return response.ok;
} catch {
return false;
}
};
Readable.fromWeb()这个实现为Docker部署环境提供了完整、可靠、易维护的API代理解决方案。