本次提交主要对 Docker 代理功能进行了优化,并完善了相关的错误处理逻辑。具体内容包括: - 精确匹配 API 代理路径,使用 `location =` 确保 Nginx 配置中的代理路径精确匹配,避免被其他正则匹配拦截。 - 添加对本地主机 URL 的自动转换支持,在 Docker 容器内部访问宿主机时,自动将 `localhost`、`127.0.0.1` 等地址转换为 `host.docker.internal`。 - 优化 ModelManager 组件,将 `useDockerProxy` 选项添加到模型配置中,调整 API URL 和 API Key 的输入位置,增强用户体验。 - 完善错误处理逻辑,为 Node Proxy 服务增加更详细的错误处理,并提供统一的 JSON 错误响应格式。 - 在开发环境的 `docker-compose.dev.yml` 文件中添加 `host.docker.internal` 映射,允许容器访问宿主机。 - 更新了相关文档,包括架构对比、实施计划和设计文档,详细描述了 Docker 代理功能的实现原理和使用方法。 - 调整了文档的分类和归档方式,将经验记录归档到 archives 目录。
157 lines
5.1 KiB
Nginx Configuration File
157 lines
5.1 KiB
Nginx Configuration File
server {
|
|
listen ${NGINX_PORT};
|
|
server_name _;
|
|
root /usr/share/nginx/html;
|
|
index index.html;
|
|
|
|
# 安全相关头部
|
|
add_header X-Frame-Options "SAMEORIGIN" always;
|
|
add_header X-XSS-Protection "1; mode=block" always;
|
|
add_header X-Content-Type-Options "nosniff" always;
|
|
add_header Referrer-Policy "no-referrer-when-downgrade" always;
|
|
add_header Content-Security-Policy "default-src 'self' https: http: data: blob: 'unsafe-inline'; connect-src 'self' https: http: ws: wss:" always;
|
|
|
|
# 启用gzip压缩
|
|
gzip on;
|
|
gzip_vary on;
|
|
gzip_proxied any;
|
|
gzip_comp_level 6;
|
|
gzip_types text/plain text/css text/xml application/json application/javascript application/xml+rss text/javascript application/x-javascript image/svg+xml;
|
|
gzip_min_length 1000;
|
|
|
|
# 客户端缓存控制
|
|
location /assets {
|
|
expires 7d;
|
|
add_header Cache-Control "public, no-transform";
|
|
try_files $uri $uri/ =404;
|
|
}
|
|
|
|
# MCP服务器代理
|
|
location /mcp {
|
|
proxy_pass http://localhost:3000;
|
|
proxy_http_version 1.1;
|
|
proxy_set_header Upgrade $http_upgrade;
|
|
proxy_set_header Connection 'upgrade';
|
|
proxy_set_header Host $host;
|
|
proxy_set_header X-Real-IP $remote_addr;
|
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
proxy_set_header X-Forwarded-Proto $scheme;
|
|
proxy_cache_bypass $http_upgrade;
|
|
proxy_read_timeout 300s;
|
|
proxy_connect_timeout 75s;
|
|
|
|
# CORS headers for MCP
|
|
add_header Access-Control-Allow-Origin * always;
|
|
add_header Access-Control-Allow-Methods "GET, POST, OPTIONS" always;
|
|
add_header Access-Control-Allow-Headers "Content-Type, Authorization" always;
|
|
|
|
# Handle preflight requests
|
|
if ($request_method = 'OPTIONS') {
|
|
add_header Access-Control-Allow-Origin * always;
|
|
add_header Access-Control-Allow-Methods "GET, POST, OPTIONS" always;
|
|
add_header Access-Control-Allow-Headers "Content-Type, Authorization" always;
|
|
add_header Access-Control-Max-Age 1728000;
|
|
add_header Content-Type 'text/plain charset=UTF-8';
|
|
add_header Content-Length 0;
|
|
return 204;
|
|
}
|
|
}
|
|
|
|
# API代理服务(转发到Node Proxy)(精确匹配,避免被正则匹配拦截)
|
|
location = /api/proxy {
|
|
# 本地转发到Node Proxy(避免nginx动态代理复杂性)
|
|
proxy_pass http://127.0.0.1:3001;
|
|
proxy_http_version 1.1;
|
|
|
|
# 透传关键信息
|
|
proxy_set_header X-Real-IP $remote_addr;
|
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
proxy_set_header X-Forwarded-Proto $scheme;
|
|
|
|
# CORS由Node Proxy统一处理,避免重复头
|
|
}
|
|
|
|
# 流式API代理(转发到Node Proxy)(精确匹配,避免被正则匹配拦截)
|
|
location = /api/stream {
|
|
proxy_pass http://127.0.0.1:3001;
|
|
proxy_http_version 1.1;
|
|
|
|
# 流式转发配置
|
|
proxy_buffering off;
|
|
proxy_request_buffering off;
|
|
add_header X-Accel-Buffering no always;
|
|
|
|
# 透传关键信息
|
|
proxy_set_header X-Real-IP $remote_addr;
|
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
proxy_set_header X-Forwarded-Proto $scheme;
|
|
|
|
# CORS由Node Proxy统一处理,避免重复头
|
|
}
|
|
|
|
# Docker环境状态检测(精确匹配,避免被正则匹配拦截)
|
|
location = /api/docker-status {
|
|
add_header Content-Type 'application/json';
|
|
# CORS由前端同源请求处理,无需额外设置
|
|
|
|
return 200 '{"status": "available", "environment": "docker"}';
|
|
}
|
|
|
|
# SPA应用路由支持
|
|
location / {
|
|
# 引入Basic认证配置
|
|
include /etc/nginx/conf.d/auth.conf;
|
|
|
|
try_files $uri $uri/ /index.html;
|
|
expires -1;
|
|
add_header Cache-Control "no-store, no-cache, must-revalidate";
|
|
}
|
|
|
|
# 禁止访问隐藏文件
|
|
location ~ /\. {
|
|
deny all;
|
|
access_log off;
|
|
log_not_found off;
|
|
}
|
|
|
|
# API路径的JSON错误响应
|
|
location ~ ^/api/ {
|
|
# 如果Node Proxy不可用,返回JSON错误
|
|
error_page 502 503 504 = @api_error;
|
|
}
|
|
|
|
location @api_error {
|
|
add_header Content-Type 'application/json' always;
|
|
add_header Access-Control-Allow-Origin * always;
|
|
return 502 '{"error": "Proxy service temporarily unavailable"}';
|
|
}
|
|
|
|
# 普通页面错误配置
|
|
error_page 404 /index.html;
|
|
error_page 500 502 503 504 /50x.html;
|
|
location = /50x.html {
|
|
root /usr/share/nginx/html;
|
|
}
|
|
|
|
# 性能优化:关闭访问日志,只记录错误
|
|
access_log off;
|
|
error_log /var/log/nginx/error.log error;
|
|
|
|
# 禁止特定请求方法
|
|
if ($request_method !~ ^(GET|HEAD|POST|PUT|DELETE|OPTIONS)$) {
|
|
return 444;
|
|
}
|
|
|
|
# 配置较大文件的传输
|
|
client_max_body_size 50m;
|
|
client_body_buffer_size 128k;
|
|
|
|
# 连接超时设置
|
|
keepalive_timeout 65;
|
|
client_header_timeout 60;
|
|
client_body_timeout 60;
|
|
send_timeout 60;
|
|
proxy_connect_timeout 60;
|
|
proxy_send_timeout 60;
|
|
proxy_read_timeout 60;
|
|
} |