class Stash::Sword::HTTPHelper

Utility class simplifying GET requests for HTTP/HTTPS resources.

Constants

DEFAULT_MAX_REDIRECTS

The default number of redirects to follow before erroring out.

DEFAULT_TIMEOUT

The default number of seconds to allow before timing out. Defaults to 10 minutes.

Attributes

password[R]

@return [String] the HTTP Basic Authentication password

redirect_limit[RW]

@return [Integer] the number of redirects to follow before erroring out

timeout[RW]

@return [Integer] the number of seconds to allow before timing out

user_agent[RW]

@return [String] the User-Agent string to send when making requests

username[R]

@return [String] the HTTP Basic Authentication username

Public Class Methods

new(user_agent:, username: nil, password: nil, redirect_limit: DEFAULT_MAX_REDIRECTS, timeout: DEFAULT_TIMEOUT, logger: nil) click to toggle source

Creates a new `HTTPHelper`

@param user_agent [String] the User-Agent string to send when making requests @param redirect_limit [Integer] the number of redirects to follow before erroring out

(defaults to {DEFAULT_MAX_REDIRECTS})

@param logger [Logger, nil] the logger to use, or nil to use a default logger

# File lib/stash/sword/http_helper.rb, line 40
def initialize(user_agent:, username: nil, password: nil, redirect_limit: DEFAULT_MAX_REDIRECTS, timeout: DEFAULT_TIMEOUT, logger: nil) # rubocop:disable Metrics/ParameterLists
  @user_agent = user_agent
  @redirect_limit = redirect_limit
  @timeout = timeout
  @username = username
  @password = password
  @log = logger || default_logger
end

Public Instance Methods

get(uri:, limit: redirect_limit) click to toggle source

Gets the content of the specified URI as a string. @param uri [URI] the URI to download @param limit [Integer] the number of redirects to follow (defaults to {#redirect_limit}) @return [String] the content of the URI

# File lib/stash/sword/http_helper.rb, line 53
def get(uri:, limit: redirect_limit)
  do_get(uri, limit) do |success|
    # not 100% clear why we need an explicit return here; it
    # doesn't show up in unit tests but it does in example.rb
    return success.body
  end
end
post(uri:, payload:, headers: {}, limit: redirect_limit) click to toggle source

Posts the specified payload string to the specified URI.

# File lib/stash/sword/http_helper.rb, line 62
def post(uri:, payload:, headers: {}, limit: redirect_limit)
  do_post_or_put(method: :post, uri: uri, payload: payload, headers: headers, limit: limit, timeout: timeout)
end
put(uri:, payload:, headers: {}, limit: redirect_limit) click to toggle source

Puts the specified payload string to the specified URI.

# File lib/stash/sword/http_helper.rb, line 67
def put(uri:, payload:, headers: {}, limit: redirect_limit)
  do_post_or_put(method: :put, uri: uri, payload: payload, headers: headers, limit: limit, timeout: timeout)
end

Private Instance Methods

default_headers() click to toggle source
# File lib/stash/sword/http_helper.rb, line 73
def default_headers
  {
    'User-Agent' => user_agent,
    'Content-Transfer-Encoding' => 'binary'
  }.freeze
end
do_get(uri, limit) { |response| ... } click to toggle source

TODO: Consider rewriting with RestClient

# File lib/stash/sword/http_helper.rb, line 102
def do_get(uri, limit, &block) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
  raise "Redirect limit (#{redirect_limit}) exceeded retrieving URI #{uri}" if limit <= 0
  req = Net::HTTP::Get.new(uri, 'User-Agent' => user_agent)
  req.basic_auth(username, password) if username && password
  Net::HTTP.start(uri.hostname, uri.port, use_ssl: (uri.scheme == 'https')) do |http|
    http.request(req) do |response|
      case response
      when Net::HTTPSuccess
        yield(response)
      when Net::HTTPInformation, Net::HTTPRedirection
        do_get(redirect_uri_for(response, uri), limit - 1, &block)
      else
        raise "Error #{response.code}: #{response.message} retrieving URI #{uri}"
      end
    end
  end
end
do_post_or_put(method:, uri:, payload:, headers:, limit:, timeout:) click to toggle source
# File lib/stash/sword/http_helper.rb, line 80
def do_post_or_put(method:, uri:, payload:, headers:, limit:, timeout:) # rubocop:disable Metrics/ParameterLists
  options = request_options(headers, limit, method, payload, uri, timeout)
  log_hash(options)
  RestClient::Request.execute(**options)
end
redirect_uri_for(response, original_uri) click to toggle source
# File lib/stash/sword/http_helper.rb, line 120
def redirect_uri_for(response, original_uri)
  if response.is_a?(Net::HTTPInformation)
    original_uri
  else
    location = response['location']
    new_uri = URI(location)
    new_uri.relative? ? original_uri + location : new_uri
  end
end
request_options(headers, limit, method, payload, uri, timeout) click to toggle source
# File lib/stash/sword/http_helper.rb, line 86
def request_options(headers, limit, method, payload, uri, timeout) # rubocop:disable Metrics/MethodLength, Metrics/ParameterLists
  options = {
    method: method,
    url: uri.to_s,
    payload: payload,
    headers: headers.merge(default_headers),
    max_redirects: limit,
    open_timeout: timeout,
    read_timeout: timeout
  }
  options[:user] = username if username
  options[:password] = password if password
  options
end