Files
ocdp-go/infra/nginx/default.conf
Ivan087 ef961d4ade fix: add CORS support and nginx proxy configuration for API requests
- Add localhost to ALLOWED_DEV_ORIGINS in backend/docker-compose.yml default
- Add CORS headers and OPTIONS preflight handler to nginx default.conf
- Fix CSP header for API location block
2026-04-15 17:18:43 +08:00

78 lines
3.7 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# default.conf - OCDP production gateway
# - 对外监听 80/443Docker 默认映射宿主 80/443
# - 路由策略: /api/* → backend 服务,其余路径 → Next.js 前端
# - TLS 证书通过 /etc/nginx/certs/tls.(crt|key) 挂载,可替换为正式证书
# - 包含安全 headers: CORS, CSP, X-Frame-Options, etc.
# Security headers map
map $request_uri $csp_header {
~^\/api\/ "default-src 'none'; script-src 'self'; connect-src 'self'; frame-ancestors 'none';";
default "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; connect-src 'self' http://localhost:* https://*; frame-ancestors 'none'; form-action 'self'; base-uri 'self';";
}
server {
listen 80 default_server;
listen 443 ssl http2 default_server;
server_name _;
ssl_certificate /etc/nginx/certs/tls.crt;
ssl_certificate_key /etc/nginx/certs/tls.key;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256';
ssl_prefer_server_ciphers on;
# Security headers for all responses
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "accelerometer=(), camera=(), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), payment=(), usb=()" always;
# 前端 Next.js 服务代理 - 所有非 API 请求
location / {
add_header Content-Security-Policy $csp_header always;
proxy_pass http://ocdp-frontend:3000;
proxy_http_version 1.1;
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_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_cache_bypass $http_upgrade;
}
# API 请求代理到 backend 服务
location /api/ {
# Allow CORS for API endpoints
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization';
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain; charset=utf-8';
add_header 'Content-Length' 0;
return 204;
}
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization' always;
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range' always;
proxy_pass http://ocdp-backend:8080;
proxy_http_version 1.1;
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;
}
# Nginx 健康检查
location = /healthz {
access_log off;
add_header Content-Type text/plain;
return 200 'ok';
}
}