Skip to content

Instantly share code, notes, and snippets.

@trevorrowe
Last active October 19, 2017 00:07
Show Gist options
  • Save trevorrowe/ae55df222d45cb424366c98bdc5e1e4e to your computer and use it in GitHub Desktop.
Save trevorrowe/ae55df222d45cb424366c98bdc5e1e4e to your computer and use it in GitHub Desktop.
AWS SDK for Ruby v2 pluggable HTTP client example
#!/usr/bin/env ruby
require 'aws-sdk'
# This example produces empty http responses, but gives some general structure and guiance.
class DummyHttpHandler < Seahorse::Client::Handler
def call(context)
context.http_request.endpoint # HTTP or HTTPS URI
context.http_request.http_method # 'GET', 'POST', etc
context.http_request.headers # headers hash
context.body # IO object that should be streamed
context.http_response.signal_headers(200, {}) # status code, headers
context.http_response.signal_data('') # call this as bytes are received, avoid
context.http_response.signal_data('') # buffering the entire body into memory
context.http_response.signal_done
# Call signal error with an error object (extends StandardError).
# Wrap this error in a networking error if it is transport related.
# Using networking error indicates that it should be retried.
# No need to call #signal_done if you call #signal_error
#
# # non-retryable error
# context.signal_error(err)
#
# # retryable transport error error
# context.signal_error(Seahorse::Client::NetworkingError.new(err))
Seahorse::Client::Response.new(context: context)
end
end
class DummyHttpPlugin < Seahorse::Client::Plugin
def add_handlers(handlers, config)
handlers.add(DummyHttpHandler, step: :send)
end
end
Aws::S3::Client.add_plugin(DummyHttpPlugin)
s3 = Aws::S3::Client.new
s3.head_object(bucket: 'aws-sdk', key: 'foo')
#!/usr/bin/env ruby
require 'excon'
require 'aws-sdk'
# This is a functional example using excon with a few limitations:
#
# * Not using excon streaming interface. The entire http response body
# is being loaded into memory.
# * No configurable networking settings. This can be exposed via
# the plugin and passed through to the handler as part of context.config
# * Not establishing persistent connections. A connection pool is needed
# if you want to share persistent connections across requests.
#
class ExconHandler < Seahorse::Client::Handler
def call(context)
req = context.http_request
resp = context.http_response
# Ugh, excon sends a Host header with the host header when both are present,
# same for user-agent. Converting to title-case to prevent double headers
# which was causing authentication errors.
headers = req.headers.to_h
headers['Host'] = headers.delete('host')
headers['User-Agent'] = headers.delete('user-agent')
connection = Excon.new(req.endpoint.to_s)
begin
excon_resp = connection.request({
method: req.http_method,
headers: headers,
body: req.body,
})
resp.signal_headers(excon_resp.status.to_i, excon_resp.headers)
resp.signal_data(excon_resp.body)
resp.signal_done
rescue Excon::Errors::SocketError => error
# retried
resp.signal_error(Seahorse::Client::NetworkingError.new(error))
rescue => error
# not retried
resp.signal_error(error)
end
Seahorse::Client::Response.new(context: context)
end
end
class ExconPlugin < Seahorse::Client::Plugin
def add_handlers(handlers, config)
handlers.add(ExconHandler, step: :send)
end
end
Aws::S3::Client.add_plugin(ExconPlugin)
s3 = Aws::S3::Client.new
s3.list_objects(bucket:'aws-sdk').contents.each do |obj|
puts obj.key
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment