diff --git a/gems/aws-sdk-core/CHANGELOG.md b/gems/aws-sdk-core/CHANGELOG.md index 05e3131d8f3..4b2d0f04e4a 100644 --- a/gems/aws-sdk-core/CHANGELOG.md +++ b/gems/aws-sdk-core/CHANGELOG.md @@ -1,6 +1,8 @@ Unreleased Changes ------------------ +* Issue - Don't retry streaming requests with blocks (#2311) + 3.99.1 (2020-06-11) ------------------ diff --git a/gems/aws-sdk-core/lib/seahorse/client/block_io.rb b/gems/aws-sdk-core/lib/seahorse/client/block_io.rb index 75af80c8689..9430ae6e99a 100644 --- a/gems/aws-sdk-core/lib/seahorse/client/block_io.rb +++ b/gems/aws-sdk-core/lib/seahorse/client/block_io.rb @@ -11,6 +11,7 @@ def initialize(&block) # @return [Integer] def write(chunk) @block.call(chunk) + ensure chunk.bytesize.tap { |chunk_size| @size += chunk_size } end diff --git a/gems/aws-sdk-core/lib/seahorse/client/plugins/response_target.rb b/gems/aws-sdk-core/lib/seahorse/client/plugins/response_target.rb index 9e003b74e36..64de371250f 100644 --- a/gems/aws-sdk-core/lib/seahorse/client/plugins/response_target.rb +++ b/gems/aws-sdk-core/lib/seahorse/client/plugins/response_target.rb @@ -28,7 +28,13 @@ def call(context) def add_event_listeners(context, target) handler = self context.http_response.on_headers(200..299) do - context.http_response.body = handler.send(:io, target) + # In a fresh response body will be a StringIO + # However, when a request is retried we may have + # an existing ManagedFile or BlockIO and those + # should be reused. + if context.http_response.body.is_a? StringIO + context.http_response.body = handler.send(:io, target) + end end context.http_response.on_success(200..299) do @@ -40,15 +46,18 @@ def add_event_listeners(context, target) context.http_response.on_error do body = context.http_response.body - File.unlink(body) if ManagedFile === body + + # When using response_target of file we do not want to write + # error messages to the file. So set the body to a new StringIO + if body.is_a? ManagedFile + File.unlink(body) + context.http_response.body = StringIO.new + end + # Aws::S3::Encryption::DecryptHandler (with lower priority) # has callbacks registered after ResponseTarget::Handler, # where http_response.body is an IODecrypter - # and has error callbacks handling for it. - # Thus avoid early remove of IODecrypter at ResponseTarget::Handler - unless context.http_response.body.respond_to?(:io) - context.http_response.body = StringIO.new - end + # and has error callbacks handling for it so no action is required here end end diff --git a/gems/aws-sdk-s3/lib/aws-sdk-s3/encryption/io_decrypter.rb b/gems/aws-sdk-s3/lib/aws-sdk-s3/encryption/io_decrypter.rb index 68273738a90..48e0ec26d50 100644 --- a/gems/aws-sdk-s3/lib/aws-sdk-s3/encryption/io_decrypter.rb +++ b/gems/aws-sdk-s3/lib/aws-sdk-s3/encryption/io_decrypter.rb @@ -8,7 +8,8 @@ class IODecrypter # @param [IO#write] io An IO-like object that responds to `#write`. def initialize(cipher, io) @cipher = cipher.clone - @io = io + # Ensure that IO is reset between retries + @io = io.tap { |io| io.truncate(0) if io.respond_to?(:truncate) } end # @return [#write] @@ -23,6 +24,10 @@ def finalize @io.write(@cipher.final) end + def size + @io.size + end + end end end