主题素材可放任意 S3 兼容存储,生成器内测通后一键上传

素材位置改成两选一(本地随二进制 / 自行填 Endpoint 的 S3 兼容存储),
R2、MinIO、B2、OSS-COS 的 S3 端点都只差 Endpoint/Region/路径风格。

- serve.py:手写 SigV4(PUT/GET/DELETE/HEAD),新增 /api/s3/test 与
  /api/s3/upload。测试连接依次验连通、写权限、读回一致、匿名可读,
  失败把 S3 的 <Code> 翻成可执行的建议;上传带 immutable 缓存头。
- index.html:新增「素材托管」面板(模式切换 + 7 个字段 + 测试/上传按钮),
  上传集合与导出共用 usedAssetIds();成功后自动回填「素材前缀」。
  密钥只进 sessionStorage 与内存,不进草稿/工程 json/导出 zip。
- 修:usedAssetIds 返回 Set,误用 length/map 导致「还没有素材」。
- 修:字段填完 700ms 内刷新会丢配置 → 失焦与模式切换时立即落盘。
- 自检:check_sigv4.py 与 aws-sdk-go-v2 signer 逐字节对拍(6/6),
  selftest_upload.py 起假 S3 跑通测试连接→上传→读回(16 项),
  mock_s3.py 供手动点面板用。
This commit is contained in:
tamakyi
2026-10-21 21:08:39 +08:00
parent 6c21184733
commit 9c961b3c05
9 changed files with 1220 additions and 30 deletions
+51
View File
@@ -0,0 +1,51 @@
// 临时校验程序:用 aws-sdk-go-v2 的 SigV4 signer 给同一请求签名,
// 与 dev/theme-builder/serve.py 手写的实现比对。验证完即删。
//
// 每行 stdin:method \t url \t region \t payloadHash \t amzDate
package main
import (
"bufio"
"context"
"fmt"
"net/http"
"os"
"strings"
"time"
v4 "github.com/aws/aws-sdk-go-v2/aws/signer/v4"
"github.com/aws/aws-sdk-go-v2/credentials"
)
func main() {
keyID := os.Getenv("AWS_KEY_ID")
secret := os.Getenv("AWS_SECRET")
s := bufio.NewScanner(os.Stdin)
for s.Scan() {
line := strings.TrimSpace(s.Text())
if line == "" {
continue
}
f := strings.Split(line, "\t")
method, urlStr, region, payloadHash, ts := f[0], f[1], f[2], f[3], f[4]
t, err := time.Parse("20060102T150405Z", ts)
if err != nil {
panic(err)
}
req, err := http.NewRequest(method, urlStr, nil)
if err != nil {
panic(err)
}
req.Header.Set("X-Amz-Content-Sha256", payloadHash)
creds := credentials.NewStaticCredentialsProvider(keyID, secret, "")
c, err := creds.Retrieve(context.Background())
if err != nil {
panic(err)
}
if err := v4.NewSigner().SignHTTP(context.Background(), c, req, payloadHash, "s3", region, t); err != nil {
panic(err)
}
fmt.Println(req.Header.Get("Authorization"))
}
}