class Aws::Plugins::ChecksumAlgorithm::ChecksumHandler

@api private

def add_verify_response_checksum_handlers(context)

verification is done only once a successful response has completed
This prevents the body from being read multiple times
Add events to the http_response to verify the checksum as its read
def add_verify_response_checksum_handlers(context)
  http_response = context.http_response
  checksum_context = { }
  http_response.on_headers do |_status, headers|
    header_name, algorithm = response_header_to_verify(headers, context[:http_checksum][:validation_list])
    if header_name
      expected = headers[header_name]
      unless context[:http_checksum][:skip_on_suffix] && /-[\d]+$/.match(expected)
        checksum_context[:algorithm] = algorithm
        checksum_context[:header_name] = header_name
        checksum_context[:digest] = ChecksumAlgorithm.digest_for_algorithm(algorithm)
        checksum_context[:expected] = expected
      end
    end
  end
  http_response.on_data do |chunk|
    checksum_context[:digest].update(chunk) if checksum_context[:digest]
  end
  http_response.on_success do
    if checksum_context[:digest] &&
      (computed = checksum_context[:digest].base64digest)
      if computed != checksum_context[:expected]
        raise Aws::Errors::ChecksumError,
              "Checksum validation failed on #{checksum_context[:header_name]} "\
              "computed: #{computed}, expected: #{checksum_context[:expected]}"
      end
      context[:http_checksum][:validated] = checksum_context[:algorithm]
    end
  end
end

def apply_request_trailer_checksum(context, checksum_properties)

def apply_request_trailer_checksum(context, checksum_properties)
  location_name = checksum_properties['name']
  # set required headers
  headers = context.http_request.headers
  headers['Content-Encoding'] = 'aws-chunked'
  headers['X-Amz-Content-Sha256'] = 'STREAMING-UNSIGNED-PAYLOAD-TRAILER'
  headers['X-Amz-Trailer'] = location_name
  # We currently always compute the size in the modified body wrapper - allowing us
  # to set the Content-Length header (set by content_length plugin).
  # This means we cannot use Transfer-Encoding=chunked
  if !context.http_request.body.respond_to?(:size)
    raise Aws::Errors::ChecksumError, 'Could not determine length of the body'
  end
  headers['X-Amz-Decoded-Content-Length'] = context.http_request.body.size
  context.http_request.body = AwsChunkedTrailerDigestIO.new(
    context.http_request.body,
    checksum_properties['algorithm'],
    location_name
  )
end

def calculate_request_checksum(context, checksum_properties)

def calculate_request_checksum(context, checksum_properties)
  case checksum_properties['in']
  when 'header'
    header_name = checksum_properties['name']
    body = context.http_request.body_contents
    if body
      context.http_request.headers[header_name] ||=
        ChecksumAlgorithm.calculate_checksum(checksum_properties['algorithm'], body)
    end
  when 'trailer'
    apply_request_trailer_checksum(context, checksum_properties)
  end
end

def call(context)

def call(context)
  if should_calculate_request_checksum?(context)
    request_algorithm_input = ChecksumAlgorithm.request_algorithm_selection(context)
    context[:checksum_algorithms] = request_algorithm_input
    request_checksum_property = {
      'algorithm' => request_algorithm_input,
      'in' => checksum_request_in(context),
      'name' => "x-amz-checksum-#{request_algorithm_input.downcase}"
    }
    calculate_request_checksum(context, request_checksum_property)
  end
  if should_verify_response_checksum?(context)
    add_verify_response_checksum_handlers(context)
  end
  @handler.call(context)
end

def checksum_request_in(context)

determine where (header vs trailer) a request checksum should be added
def checksum_request_in(context)
  if context.operation['authtype'].eql?('v4-unsigned-body')
    'trailer'
  else
    'header'
  end
end

def response_header_to_verify(headers, validation_list)

returns nil if no headers to verify
def response_header_to_verify(headers, validation_list)
  validation_list.each do |algorithm|
    header_name = "x-amz-checksum-#{algorithm}"
    return [header_name, algorithm] if headers[header_name]
  end
  nil
end

def should_calculate_request_checksum?(context)

def should_calculate_request_checksum?(context)
  context.operation.http_checksum &&
    ChecksumAlgorithm.request_algorithm_selection(context)
end

def should_verify_response_checksum?(context)

def should_verify_response_checksum?(context)
  context[:http_checksum][:validation_list] && !context[:http_checksum][:validation_list].empty?
end