Files
Genarrative/deploy/nginx/genarrative-dev-http.conf
T
lhk229 51cb05f418
Project CI / AI game creator shell Rust crates (push) Successful in 5m56s
Project CI / AI game creator shell Rust lane 2/2 (push) Successful in 6m36s
Project CI / AI game creator shell Rust lane 1/2 (push) Successful in 7m37s
Project CI / Backend tests (push) Successful in 9m22s
Project CI / Frontend tests (push) Successful in 4m40s
Project CI / AI game creator shell web tests (push) Successful in 3m50s
Project CI / Repository checks (push) Successful in 6m30s
Project CI / Native shell tests (push) Successful in 8m32s
补充创作者主页与关注粉丝工程文档 (#638)
本 PR 补齐创作者主页与关注粉丝功能的产品合同和工程设计,供后续按里程碑实施;本次只修改文档。

桌面导航第四项进入自己的创作者主页,“我的”移到第五项。游戏详情可进入作者主页并关注/取消关注;自己或他人的关注、粉丝列表均公开可查看,点击用户头像或昵称可进入其主页。本人支持取消/重新关注、回关和移除粉丝,并明确两个关注方向独立。

工程设计包含关系表与 DTO、认证和事务边界、跨页状态同步、共享组件、深链及验收要求,拆分关系查询和页面交互两个里程碑。按用户要求,游戏列表沿用最多 48 项的现有限制,不增加游戏目录分页改造。

验证:
- 已合入最新 origin/master(21c79f54a);共享决策记录冲突保留双方新增内容。
- npm run check:encoding 通过。
- npm run check:doc-index 通过。
- git diff --check 与暂存差异检查通过。
- 相对 master 仅六份文档发生变化;没有业务代码或 schema 修改,未执行业务测试或部署。

Reviewed-on: #638
Co-authored-by: Linghong <ink29535@proton.me>
Co-committed-by: Linghong <ink29535@proton.me>
2026-10-05 22:05:11 +08:00

243 lines
7.6 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.
# 开发服无域名时使用的 HTTP 入口,只允许用于 DEPLOY_TARGET=development。
# 没有域名时,将 SERVER_NAME 填为开发机 IP 或临时主机名。
# 生产 release 仍必须使用 genarrative.conf 的 HTTPS 配置。
log_format genarrative_upstream
'$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" "$http_user_agent" '
'request_time=$request_time upstream_connect_time=$upstream_connect_time '
'upstream_header_time=$upstream_header_time upstream_response_time=$upstream_response_time '
'upstream_status=$upstream_status request_id=$request_id';
upstream genarrative_api {
server 127.0.0.1:8082;
keepalive 64;
}
limit_conn_zone $binary_remote_addr zone=genarrative_api_conn:10m;
limit_req_zone $binary_remote_addr zone=genarrative_api_rps:10m rate=300r/s;
limit_req_zone $binary_remote_addr zone=genarrative_admin_rps:10m rate=30r/s;
# 维护期间允许真实 TCP 内网来源继续访问整站;不信任请求头伪造的客户端地址。
geo $remote_addr $genarrative_internal_client {
default 0;
127.0.0.0/8 1;
10.0.0.0/8 1;
172.16.0.0/12 1;
192.168.0.0/16 1;
169.254.0.0/16 1;
::1 1;
fc00::/7 1;
fe80::/10 1;
}
server {
listen 80;
server_name genarrative.example.com;
access_log /var/log/nginx/genarrative.access.log genarrative_upstream;
error_log /var/log/nginx/genarrative.error.log warn;
limit_conn_status 429;
limit_conn_log_level warn;
limit_req_status 429;
limit_req_log_level warn;
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 5;
gzip_min_length 1024;
gzip_types
text/plain
text/css
text/javascript
application/javascript
application/json
application/xml
application/xml+rss
image/svg+xml;
# __GENARRATIVE_BROTLI_DIRECTIVES__
root /srv/genarrative/web;
index index.html;
include /etc/nginx/snippets/genarrative-maintenance.conf;
location ^~ /admin/api/ {
default_type application/json;
limit_conn genarrative_api_conn 64;
limit_req zone=genarrative_admin_rps burst=16 nodelay;
if ($genarrative_maintenance) {
return 503 '{"ok":false,"error":{"code":"MAINTENANCE","message":"服务维护中"}}';
}
proxy_pass http://genarrative_api/admin/api/;
proxy_http_version 1.1;
proxy_set_header Connection "";
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;
}
location = /admin {
error_page 503 /maintenance.html;
if ($genarrative_maintenance) {
return 503;
}
return 301 /admin/;
}
location ^~ /admin/assets/ {
error_page 503 /maintenance.html;
if ($genarrative_maintenance) {
return 503;
}
try_files $uri =404;
}
location ^~ /admin/ {
error_page 503 /maintenance.html;
if ($genarrative_maintenance) {
return 503;
}
try_files $uri $uri/ /admin/index.html;
}
location ^~ /assets/ {
try_files $uri =404;
}
# 临时兼容主站仍在使用的 /api/* HTTP facade;前端完成 SpacetimeDB SDK 迁移后删除。
location ~ ^/api(?:/|$) {
default_type application/json;
# 中文注释:创作接口会携带参考图 Data URL,游戏发行包 PUT 更大,Nginx 只负责放行到 api-server;
# 真实大小限制仍由路由 DefaultBodyLimit(发行包 200 MiB + 1 KiB)和业务字节校验负责。
client_max_body_size 210m;
limit_conn genarrative_api_conn 64;
limit_req zone=genarrative_api_rps burst=64 nodelay;
if ($genarrative_maintenance) {
return 503 '{"ok":false,"error":{"code":"MAINTENANCE","message":"服务维护中"}}';
}
proxy_pass http://genarrative_api;
proxy_http_version 1.1;
proxy_buffering off;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
add_header X-Accel-Buffering no always;
proxy_set_header Connection "";
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-Forwarded-Host $host;
proxy_set_header X-Request-Id $request_id;
}
# 开发服仍不恢复旧生成资源代理和健康检查公网入口。
location ~ ^/(generated-|healthz|readyz) {
return 404;
}
# 仅开放前端 SpacetimeDB SDK 运行所需的最小公网路由。
location ~ ^/v1/database/[^/]+/subscribe$ {
if ($genarrative_maintenance) {
return 503;
}
proxy_pass http://127.0.0.1:3101;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host $host;
proxy_read_timeout 3600s;
}
location ^~ /v1/identity {
if ($genarrative_maintenance) {
return 503;
}
proxy_pass http://127.0.0.1:3101;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host $host;
}
location ^~ /v1/ {
return 404;
}
# 平台同源路径发行入口:/games/<gameId>/ 与 /games/<gameId>/<asset> 映射到
# api-server 发行网关。游戏文档跑在 iframe sandbox="allow-scripts" 的不透明来源里,
# 离开页面即随 iframe 卸载,因此不再要求独立发行域名与通配证书。
location ~ "^/games/(?<game_id>game_[0-9a-f]{32})(?<game_path>/.*)?$" {
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_api/api/game-distribution/releases/$game_id$game_path;
proxy_read_timeout 60s;
proxy_send_timeout 60s;
}
# BEGIN GENARRATIVE MAIN SPA ROUTES
location = / {
error_page 503 /maintenance.html;
if ($genarrative_maintenance) {
return 503;
}
try_files /index.html =404;
}
location ~* "^/(?:creation|editor/canvas|pay|profile|profile/payment|project|components|design-system|creators|creators/connections|games|games/detail|games/mine|games/play|games/publish)/?$" {
error_page 503 /maintenance.html;
if ($genarrative_maintenance) {
return 503;
}
try_files $uri /index.html =404;
}
# 收银台深链 `/pay/<checkoutToken>`:token 由前端从最后一个路径段读取(payment.rs 生成该链接),
# 只放行裸前缀会让真实收银台链接落到默认 location 变 404;这里只放行「/pay/ + 恰好一个路径段」。
location ~* "^/pay/[^/]+/?$" {
error_page 503 /maintenance.html;
if ($genarrative_maintenance) {
return 503;
}
try_files $uri /index.html =404;
}
# END GENARRATIVE MAIN SPA ROUTES
location / {
error_page 503 /maintenance.html;
error_page 404 /404.html;
if ($genarrative_maintenance) {
return 503;
}
try_files $uri $uri/ =404;
}
}