From ecb26b8b0fe2704c95f35df39c723c44fc196235 Mon Sep 17 00:00:00 2001 From: yourname Date: Tue, 7 Apr 2026 13:55:07 +0000 Subject: [PATCH] =?UTF-8?q?sync:=20=E6=9B=B4=E6=96=B0=20MinIO=20=C2=A78=20?= =?UTF-8?q?=E2=80=94=20dual=20S3Client=20=E6=A8=A1=E5=BC=8F=EF=BC=88?= =?UTF-8?q?=E7=A6=81=E6=AD=A2=E5=AD=97=E7=AC=A6=E4=B8=B2=E6=9B=BF=E6=8D=A2?= =?UTF-8?q?=E5=9F=9F=E5=90=8D=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.6 --- .../d8d-dev/reference/platform-nextjs.md | 26 +++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/.claude/skills/d8d-dev/reference/platform-nextjs.md b/.claude/skills/d8d-dev/reference/platform-nextjs.md index 1fe2dcc..f0cb19b 100644 --- a/.claude/skills/d8d-dev/reference/platform-nextjs.md +++ b/.claude/skills/d8d-dev/reference/platform-nextjs.md @@ -249,12 +249,34 @@ NPM 代理主机默认配置会阻断 WebSocket,导致: | `S3_ENDPOINT` | S3Client 内部连接 | `http://localhost:9000` | | `S3_PUBLIC_URL` | 对外暴露的 URL(presigned、封面) | `https://{MINIO_HOST}` | +### Dual S3Client 模式(⛔ 强制) + +AWS SDK `getSignedUrl()` 生成的 presigned URL 签名包含 `X-Amz-SignedHeaders=host`, +即签名绑定了 S3Client 的 endpoint host。**不能用字符串替换域名**(签名会失效返回 403)。 + +必须创建两个 S3Client 实例: + +```typescript +// 内部 S3Client(worker 下载、上传等) +const s3 = new S3Client({ endpoint: "http://localhost:9000", ... }); + +// 外网 S3Client(生成外网 presigned URL) +const s3Public = new S3Client({ endpoint: "https://minio-xxx.dev.d8d.fun", ... }); + +// 内部 presigned URL(worker 用) +getDownloadUrl(key) → getSignedUrl(s3, ...) // host=localhost:9000 + +// 外网 presigned URL(浏览器/stream 路由用) +getPublicDownloadUrl(key) → getSignedUrl(s3Public, ...) // host=minio-xxx.dev.d8d.fun +``` + ### 代码规则 -- **`getDownloadUrl()`**:返回内部 presigned URL(worker 下载用) -- **`getPublicDownloadUrl()`**:返回外网 presigned URL(stream 路由用,替换域名) +- **`getDownloadUrl()`**:用内部 `s3`,返回 localhost presigned URL(worker 下载用) +- **`getPublicDownloadUrl()`**:用 `s3Public`,返回外网 presigned URL(stream 路由用) - **`uploadFile()` 返回值**:使用 `S3_PUBLIC_URL`(公开访问 URL) - **worker 中的封面 URL**:使用 `S3_PUBLIC_URL` +- **禁止字符串替换域名**:`url.replace(localhost, publicUrl)` 会导致 403 ### ⚠️ HTTPS 注意