实现与 akka-http 兼容的基本 S3 API
Implementing basic S3 compatible API with akka-http
我正在尝试使用 akka-http.
实现与基本 S3 兼容 API 的文件存储 ыукмшсу
我使用 s3 java sdk 来测试我的服务 API 并发现了 putObject(...) 方法的问题。我无法在 akka-http 后端正确使用文件。为了测试目的,我写了简单的路线:
def putFile(bucket: String, file: String) = put{
extractRequestEntity{ ent =>
val finishedWriting = ent.dataBytes.runWith(FileIO.toPath(new File(s"/tmp/${file}").toPath))
onComplete(finishedWriting) { ioResult =>
complete("Finished writing data: " + ioResult)
}
}
}
它保存了文件,但文件总是损坏。查看文件内部,我发现了如下几行:
"20000;chunk-signature=73c6b865ab5899b5b7596b8c11113a8df439489da42ddb5b8d0c861a0472f8a1"
.
当我尝试使用任何其他 rest 客户端 PUT 文件时,它工作正常。
我知道 S3 使用 "Expect: 100-continue" header 并且他可能会导致问题。
我真的不知道该如何处理。任何帮助表示赞赏。
这并没有完全损坏。您的服务没有考虑 S3 支持使用 Content-Encoding: aws-chunked
和 x-amz-content-sha256: STREAMING-AWS4-HMAC-SHA256-PAYLOAD
.
在线发送上传的四种方法之一
它是一种 non-standards-based 流式传输 object 的机制,包括看起来完全像这样的块:
string(IntHexBase(chunk-size)) + ";chunk-signature=" + signature + \r\n + chunk-data + \r\n
...其中 IntHexBase()
是将整数格式化为十六进制数的函数的伪代码。
此 chunk-based algorithm 与 Transfer-Encoding: chunked
相似,但不兼容,因为它在流中嵌入了校验和。
他们为什么要编一个新的HTTP传输编码?它在客户端可能很有用,因为它消除了 "read your payload twice or buffer [the entire object payload] in memory [concurrently]" 的需要——如果您要在上传开始之前计算 x-amz-content-sha256
哈希值,那么其中一个或另一个是必需的,因为您否则必须,因为完整性检查需要它。
我不太熟悉 Java SDK 的内部结构,但是这种类型的上传 可能 通过使用 .withInputStream()
触发,或者它可能也是文件或超过一定大小的文件的标准行为。
如果您在请求 headers 中看到 x-amz-content-sha256: STREAMING-AWS4-HMAC-SHA256-PAYLOAD
,您的最低解决方法是抛出 HTTP 错误,因为您似乎没有在 API 中实现它,但这会很可能仅用于防止存储通过此方法上传的 objects。这还不是自动发生的事实表明您根本没有实现 x-amz-content-sha256
处理,因此您没有进行需要进行的 server-side 负载完整性检查。
为了完全兼容,您需要实现 S3 支持的算法,并且假定 SDK 可用,除非 SDK 特别支持禁用该算法的机制——这似乎不太可能,因为它服务于有用的目的,特别是(看起来)对于长度已知但不可搜索的流。
¹ 四分之一 -- 其他三个是标准 PUT
、web-based html 形式 POST
,以及推荐用于大文件和大于 5 GB 的文件强制使用的多部分 API。
我正在尝试使用 akka-http.
实现与基本 S3 兼容 API 的文件存储 ыукмшсу
我使用 s3 java sdk 来测试我的服务 API 并发现了 putObject(...) 方法的问题。我无法在 akka-http 后端正确使用文件。为了测试目的,我写了简单的路线:
def putFile(bucket: String, file: String) = put{
extractRequestEntity{ ent =>
val finishedWriting = ent.dataBytes.runWith(FileIO.toPath(new File(s"/tmp/${file}").toPath))
onComplete(finishedWriting) { ioResult =>
complete("Finished writing data: " + ioResult)
}
}
}
它保存了文件,但文件总是损坏。查看文件内部,我发现了如下几行:
"20000;chunk-signature=73c6b865ab5899b5b7596b8c11113a8df439489da42ddb5b8d0c861a0472f8a1"
.
当我尝试使用任何其他 rest 客户端 PUT 文件时,它工作正常。 我知道 S3 使用 "Expect: 100-continue" header 并且他可能会导致问题。 我真的不知道该如何处理。任何帮助表示赞赏。
这并没有完全损坏。您的服务没有考虑 S3 支持使用 Content-Encoding: aws-chunked
和 x-amz-content-sha256: STREAMING-AWS4-HMAC-SHA256-PAYLOAD
.
它是一种 non-standards-based 流式传输 object 的机制,包括看起来完全像这样的块:
string(IntHexBase(chunk-size)) + ";chunk-signature=" + signature + \r\n + chunk-data + \r\n
...其中 IntHexBase()
是将整数格式化为十六进制数的函数的伪代码。
此 chunk-based algorithm 与 Transfer-Encoding: chunked
相似,但不兼容,因为它在流中嵌入了校验和。
他们为什么要编一个新的HTTP传输编码?它在客户端可能很有用,因为它消除了 "read your payload twice or buffer [the entire object payload] in memory [concurrently]" 的需要——如果您要在上传开始之前计算 x-amz-content-sha256
哈希值,那么其中一个或另一个是必需的,因为您否则必须,因为完整性检查需要它。
我不太熟悉 Java SDK 的内部结构,但是这种类型的上传 可能 通过使用 .withInputStream()
触发,或者它可能也是文件或超过一定大小的文件的标准行为。
如果您在请求 headers 中看到 x-amz-content-sha256: STREAMING-AWS4-HMAC-SHA256-PAYLOAD
,您的最低解决方法是抛出 HTTP 错误,因为您似乎没有在 API 中实现它,但这会很可能仅用于防止存储通过此方法上传的 objects。这还不是自动发生的事实表明您根本没有实现 x-amz-content-sha256
处理,因此您没有进行需要进行的 server-side 负载完整性检查。
为了完全兼容,您需要实现 S3 支持的算法,并且假定 SDK 可用,除非 SDK 特别支持禁用该算法的机制——这似乎不太可能,因为它服务于有用的目的,特别是(看起来)对于长度已知但不可搜索的流。
¹ 四分之一 -- 其他三个是标准 PUT
、web-based html 形式 POST
,以及推荐用于大文件和大于 5 GB 的文件强制使用的多部分 API。