Skip to content

Commit cccbf1e

Browse files
committed
Enable streaming upload in S3 : put_object
There were two problems: 1) Request did not allow an IO 2) Signing did not permit an unsigned payload (https://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-header-based-auth.html)
1 parent 100c30e commit cccbf1e

File tree

2 files changed

+15
-11
lines changed

2 files changed

+15
-11
lines changed

src/utilities/request.jl

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ Base.@kwdef mutable struct Request
6666
request_method::String
6767

6868
headers::AbstractDict{String,String} = LittleDict{String,String}()
69-
content::Union{String,Vector{UInt8}} = ""
69+
content::Union{String,Vector{UInt8},IO} = ""
7070
resource::String = ""
7171
url::String = ""
7272

@@ -121,6 +121,12 @@ function submit_request(aws::AbstractAWSConfig, request::Request; return_headers
121121
"EC2ThrottledException",
122122
]
123123

124+
if isa(request.content, IO)
125+
request.headers["x-amz-content-sha256"] = "UNSIGNED-PAYLOAD"
126+
else
127+
request.headers["Content-MD5"] = base64encode(
128+
digest(MD_MD5, request.content))
129+
end
124130
request.headers["User-Agent"] = user_agent[]
125131
request.headers["Host"] = HTTP.URI(request.url).host
126132
stream = @something request.response_stream IOBuffer()

src/utilities/sign.jl

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -63,20 +63,18 @@ function sign_aws4!(aws::AbstractAWSConfig, request::Request, time::DateTime)
6363
# Authentication scope string...
6464
authentication_scope = join(authentication_scope, "/")
6565

66-
# SHA256 hash of content...
67-
content_hash = bytes2hex(digest(MD_SHA256, request.content))
66+
# SHA256 hash of content if data is in memory
67+
if !haskey(request.headers, "x-amz-content-sha256") && signed_content
68+
content_hash = bytes2hex(digest(MD_SHA256, request.content))
69+
request.headers["x-amz-content-sha256"] = content_hash
70+
else
71+
content_hash = "UNSIGNED-PAYLOAD"
72+
end
6873

6974
# HTTP headers...
7075
delete!(request.headers, "Authorization")
7176

72-
merge!(
73-
request.headers,
74-
Dict(
75-
"x-amz-content-sha256" => content_hash,
76-
"x-amz-date" => datetime,
77-
"Content-MD5" => base64encode(digest(MD_MD5, request.content)),
78-
),
79-
)
77+
merge!(request.headers, Dict("x-amz-date" => datetime))
8078

8179
if !isempty(creds.token)
8280
request.headers["x-amz-security-token"] = creds.token

0 commit comments

Comments
 (0)