【发布时间】:2026-01-22 19:55:01
【问题描述】:
我需要使用 Go AWS SDK 中的 GetObject 系列函数从 S3 存储桶中获取对象,其中对象的键可能以一个或多个斜杠开头。但是,SDK 似乎删除了那些前导斜杠,从而更改了密钥。
我创建了存储桶并将一些数据放入如下:
$ aws s3 mb <TEST BUCKET>
$ aws s3 cp <SOME FILE> s3://<TEST BUCKET>//leadingslash
以下代码显示ListObjects 正确返回带有前导斜杠的密钥,但是在运行时日志显示GET 请求在没有前导斜杠的情况下完成。
package main
import (
"log"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/s3"
)
func main() {
bucket := "<TEST BUCKET>"
region := "<TEST BUCKET REGION>"
config := (&aws.Config{Region: ®ion}).WithLogLevel(aws.LogDebugWithHTTPBody)
s3svc := s3.New(session.New(config))
listInput := s3.ListObjectsInput{
Bucket: &bucket,
}
listOutput, err := s3svc.ListObjects(&listInput)
if err != nil {
log.Fatalf("Failed to list objects: %v", err)
} else {
log.Printf("Good: %v", listOutput)
}
for _, object := range listOutput.Contents {
getInput := s3.GetObjectInput{
Bucket: &bucket,
Key: object.Key,
}
getOutput, err := s3svc.GetObject(&getInput)
if err != nil {
log.Fatalf("Failed to HEAD object: %v", err)
} else {
log.Printf("Good: %v", getOutput)
}
}
}
在启用调试日志记录的情况下调用 GetObject 表明 SDK 执行了以下请求:
GET /leadingslash HTTP/1.1
这缺少前导斜杠并返回 404 错误。
我应该如何使用 Go SDK 获取此类对象?我无法控制对象的密钥。
在将密钥传递给 GetObject 之前,我曾尝试对密钥进行 URL 转义,但是百分号被转义并且密钥发生了变化。
我使用 Go 1.9 linux/amd64 和 SDK 1.12.62。
【问题讨论】:
-
键中的前导斜杠从根本上说是不正确的,因为从概念上讲,URL 中的
/位于对象键中的第一个字符之前,而不是第一个字符密钥本身(很像服务器根目录中的文件实际命名foo而不是/foo,前者是名称,后者是路径)...但不幸的是,当开发人员错误地提供斜线时,大多数 SDK 都会通过吞下前导斜线来掩盖这一点。如果您无法更正错误的不正确密钥,您可能不得不破解 SDK 或滚动您自己的签名代码。
标签: amazon-s3 aws-sdk-go