# Nginx 配置文件 - AI临床研究平台前端服务 # 用途:托管 React SPA + 反向代理后端 API user nginx; worker_processes auto; # 自动根据 CPU 核心数调整 # ⚠️ 日志输出到 stderr(SAE 会自动收集) error_log /dev/stderr warn; pid /var/run/nginx.pid; events { worker_connections 1024; # 每个 worker 进程的最大连接数 use epoll; # Linux 下使用 epoll(高性能) } http { include /etc/nginx/mime.types; default_type application/octet-stream; # WebSocket / SSE 兼容:仅当请求包含 Upgrade 头时设置 Connection: upgrade # SSE 请求无 Upgrade 头 → Connection 为空,避免 HTTP/2 帧协议错误 map $http_upgrade $connection_upgrade { default upgrade; '' ''; } # ⚠️ 文件上传大小限制(默认只有 1MB,太小会导致 413 错误) client_max_body_size 50M; # 允许上传最大 50MB 文件 # 日志格式 log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; # ⚠️ 日志输出到 stdout(SAE 会自动收集,避免磁盘写满) access_log /dev/stdout main; # 性能优化 sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; types_hash_max_size 2048; # Gzip 压缩(减少传输大小) gzip on; gzip_vary on; gzip_proxied any; gzip_comp_level 6; gzip_types text/plain text/css text/xml text/javascript application/json application/javascript application/xml+rss application/rss+xml font/truetype font/opentype application/vnd.ms-fontobject image/svg+xml; gzip_disable "msie6"; # 上游后端服务(Backend Service) upstream backend { # ⚠️ 重要:这里的地址在部署时需要替换为真实的后端内网地址 # SAE 部署时,通过环境变量注入,详见 Dockerfile server ${BACKEND_SERVICE_HOST}:${BACKEND_SERVICE_PORT} fail_timeout=30s max_fails=3; # 如果有多个后端实例(负载均衡) # server 172.17.x.x:3001 weight=1; # server 172.17.x.y:3001 weight=1; keepalive 32; # 保持连接池 } server { listen 80; server_name _; # 接受所有域名 # 根目录(React 构建产物) root /usr/share/nginx/html; index index.html; # 字符集 charset utf-8; # ==================== 静态资源处理 ==================== # 主页面(index.html)- 不缓存 location = / { try_files /index.html =404; add_header Cache-Control "no-cache, no-store, must-revalidate"; add_header Pragma "no-cache"; add_header Expires "0"; } location = /index.html { add_header Cache-Control "no-cache, no-store, must-revalidate"; add_header Pragma "no-cache"; add_header Expires "0"; } # JS/CSS 文件 - 强缓存(文件名带 hash) location ~* \.(js|css)$ { expires 1y; add_header Cache-Control "public, immutable"; access_log off; } # 图片/字体文件 - 强缓存 location ~* \.(png|jpg|jpeg|gif|ico|svg|webp|woff|woff2|ttf|eot)$ { expires 1y; add_header Cache-Control "public, immutable"; access_log off; } # ==================== API 反向代理 ==================== # 微信服务号回调代理(关键!微信验证需要) location /wechat/ { # 代理到后端服务 proxy_pass http://backend; # 保留原始请求信息 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_connect_timeout 60s; proxy_send_timeout 60s; proxy_read_timeout 60s; # 缓冲配置 proxy_buffering off; # HTTP 1.1 proxy_http_version 1.1; } # 后端 API 代理(关键配置) location /api/ { # 文件上传大小限制(PKB 文档上传等场景) client_max_body_size 50M; # 代理到后端服务 proxy_pass http://backend; # 保留原始请求信息 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; # 超时配置(AI 对话、文件处理可能耗时较长) proxy_connect_timeout 300s; proxy_send_timeout 300s; proxy_read_timeout 300s; # 缓冲配置(SSE 流式响应必须关闭所有缓冲/缓存) proxy_buffering off; proxy_cache off; proxy_request_buffering off; # WebSocket + SSE 兼容 proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; # 错误处理 proxy_next_upstream error timeout invalid_header http_500 http_502 http_503; proxy_next_upstream_tries 2; } # ==================== SPA 路由支持 ==================== # React Router 路由回退 # 所有非文件请求都返回 index.html(SPA 的核心) location / { try_files $uri $uri/ /index.html; # 禁用缓存(用户刷新时总是获取最新页面) add_header Cache-Control "no-cache, no-store, must-revalidate"; } # ==================== 安全加固 ==================== # 隐藏 Nginx 版本号 server_tokens off; # 禁止访问隐藏文件 location ~ /\. { deny all; access_log off; log_not_found off; } # 禁止访问特定文件 location ~* \.(bak|config|sql|fla|psd|ini|log|sh|inc|swp|dist)$ { deny all; } # ==================== 健康检查 ==================== # SAE 健康检查端点 location /health { access_log off; return 200 "healthy\n"; add_header Content-Type text/plain; } # Nginx 状态页(用于监控) location /nginx_status { stub_status on; access_log off; # 仅允许内网访问 allow 10.0.0.0/8; allow 172.17.0.0/16; allow 192.168.0.0/16; deny all; } # ==================== 错误页面 ==================== error_page 404 /index.html; # SPA 路由回退 error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; } } }