328ac31844
- 主站:游戏广场、详情、在线游玩、网页发布与作者中心,以及共享契约与客户端服务 - 后端:module-game-distribution 领域层、SpacetimeDB 表/迁移/绑定、spacetime-client facade、api-server 路由与发行网关 - 后台:游戏审核页(待审列表、通过/拒绝、安全下架) - AGC:发布面板、本地导出包读取命令与发布服务,含默认跳过的真实链路测试 - 运维:发行来源 nginx 模板与门禁、game-distribution:publish 灰度发布开关、OSS PutObject 受控重试 - 文档:主规范、里程碑与实施计划、决策日志与踩坑记录
81 lines
3.2 KiB
Plaintext
81 lines
3.2 KiB
Plaintext
# 游戏发行来源(每游戏独立 origin)
|
||
#
|
||
# 部署前替换:
|
||
# 1) `games.example.com` 为真实发行域,并为 `*.games.example.com` 配置通配 DNS
|
||
# 与通配 TLS 证书;
|
||
# 2) `ssl_certificate` / `ssl_certificate_key` 指向该通配证书;
|
||
# 3) upstream 端口与 api-server 实际监听一致。
|
||
#
|
||
# 设计约定:
|
||
# - 每个已公开游戏使用自己的子域:`https://<gameId>.games.example.com/`;
|
||
# - 该来源只把请求映射到发行网关
|
||
# `/api/game-distribution/releases/<gameId>/…`,平台 API、后台、SPA 与上传
|
||
# 接口都不在这个来源上暴露;
|
||
# - 发行来源从不使用 Cookie:带 Cookie 的请求直接 403,转发前也会清空 Cookie;
|
||
# - `X-Content-Type-Options` / CORP / 无凭据 CORS / HTML CSP / 内容类型白名单由
|
||
# api-server 发行网关设置,这里不覆盖,避免两层策略漂移;
|
||
# - 公开版本切换与下架由后端 `publication_revision` CAS 决定,边缘只做按主机映射。
|
||
|
||
upstream genarrative_release_api {
|
||
server 127.0.0.1:8082;
|
||
keepalive 32;
|
||
}
|
||
|
||
server {
|
||
listen 80;
|
||
server_name ~^(?<game_id>[a-z0-9_]+)\.games\.example\.com$;
|
||
|
||
location /.well-known/acme-challenge/ {
|
||
root /var/www/html;
|
||
}
|
||
|
||
location / {
|
||
return 301 https://$host$request_uri;
|
||
}
|
||
}
|
||
|
||
server {
|
||
listen 443 ssl http2;
|
||
server_name ~^(?<game_id>[a-z0-9_]+)\.games\.example\.com$;
|
||
|
||
ssl_certificate /etc/letsencrypt/live/games.example.com/fullchain.pem;
|
||
ssl_certificate_key /etc/letsencrypt/live/games.example.com/privkey.pem;
|
||
|
||
access_log /var/log/nginx/genarrative-release.access.log;
|
||
error_log /var/log/nginx/genarrative-release.error.log warn;
|
||
|
||
# 发行文件是公开静态资源,从不携带平台 Cookie。带上 Cookie 的请求说明它落在
|
||
# 平台会话来源上,直接拒绝,避免发行内容被主站同源脚本读取。
|
||
if ($http_cookie) {
|
||
return 403;
|
||
}
|
||
|
||
# 子域根路径直接服务该游戏的 index.html,游戏内其余资源按相对路径原样交给
|
||
# 发行网关;这样审核通过时填写的 entryUrl 就是 https://<gameId>.games.example.com/。
|
||
location = / {
|
||
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 X-Request-Id $request_id;
|
||
proxy_set_header Cookie "";
|
||
proxy_pass http://genarrative_release_api/api/game-distribution/releases/$game_id/index.html;
|
||
proxy_read_timeout 60s;
|
||
proxy_send_timeout 60s;
|
||
}
|
||
|
||
location / {
|
||
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 X-Request-Id $request_id;
|
||
proxy_set_header Cookie "";
|
||
proxy_pass http://genarrative_release_api/api/game-distribution/releases/$game_id$request_uri;
|
||
proxy_read_timeout 60s;
|
||
proxy_send_timeout 60s;
|
||
}
|
||
}
|