visual-game-nginx.js 3.58 KB
export function renderVisualGameHttpConfig(config) {
  return `${renderFrontendMap(config)}

server {
  listen 80;
  listen [::]:80;
  server_name
${renderServerNames(config)};

  location ^~ /.well-known/acme-challenge/ {
    root ${config.nginx.acme_webroot};
  }

  location / {
    return 301 https://$host$request_uri;
  }
}
`
}

export function renderVisualGameHttpsConfig(config) {
  return `${renderFrontendMap(config)}

server {
  listen 80;
  listen [::]:80;
  server_name
${renderServerNames(config)};

  location ^~ /.well-known/acme-challenge/ {
    root ${config.nginx.acme_webroot};
  }

  location / {
    return 301 https://$host$request_uri;
  }
}

server {
  listen 443 ssl http2;
  listen [::]:443 ssl http2;
  server_name
${renderServerNames(config)};

  ssl_certificate ${config.nginx.certificate_directory}/fullchain.pem;
  ssl_certificate_key ${config.nginx.certificate_directory}/key.pem;
  ssl_protocols TLSv1.2 TLSv1.3;
  ssl_session_cache shared:${config.nginx.root_variable}_ssl:10m;
  ssl_session_timeout 1d;
  ssl_session_tickets off;

  client_max_body_size 36m;

  location = /healthz {
    proxy_pass ${config.backend_origin}/healthz;
    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;
  }

  location ^~ /api/ {
    proxy_pass ${config.backend_origin};
    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_buffering off;
    proxy_request_buffering off;
    proxy_read_timeout 300s;
    proxy_send_timeout 300s;
  }

  location = /ws/asr {
    proxy_pass ${config.backend_origin};
    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_read_timeout 60s;
    proxy_send_timeout 60s;
  }

${renderFrontendLocation(config)}
}
`
}

function renderFrontendMap(config) {
  const entries = config.domains.map((domain) => `  ${domain.hostname} ${frontendTarget(config, domain)};`)
  return `map $host $${config.nginx.root_variable} {
  hostnames;
${entries.join('\n')}
}`
}

function frontendTarget(config, domain) {
  switch (config.frontend_mode) {
    case 'static':
      return `${config.application_root}/${domain.frontend_directory}`
    case 'proxy':
      return domain.frontend_origin
    default:
      throw new Error(`不支持的 frontend_mode:${config.frontend_mode}`)
  }
}

function renderFrontendLocation(config) {
  switch (config.frontend_mode) {
    case 'static':
      return `  root $${config.nginx.root_variable};
  index index.html;

  location / {
    try_files $uri $uri/ /index.html;
  }`
    case 'proxy':
      return `  location / {
    proxy_pass $${config.nginx.root_variable};
    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";
  }`
    default:
      throw new Error(`不支持的 frontend_mode:${config.frontend_mode}`)
  }
}

function renderServerNames(config) {
  return config.domains.map((domain) => `    ${domain.hostname}`).join('\n')
}