素材位置改成两选一(本地随二进制 / 自行填 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 供手动点面板用。
52 lines
1.3 KiB
Go
52 lines
1.3 KiB
Go
// 临时校验程序:用 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"))
|
||
}
|
||
}
|