class TwitterAds::Request

Generic container for API requests.

Constants

DEFAULT_DOMAIN
HTTP_METHOD
SANDBOX_DOMAIN

Attributes

client[R]
method[R]
options[R]
resource[R]

Public Class Methods

new(client, method, resource, opts = {}) click to toggle source

Creates a new Request object instance.

@example

request = Request.new(client, :get, "/#{TwitterAds::API_VERSION}/accounts")

@param client [Client] The Client object instance. @param method [Symbol] The HTTP method to be used. @param resource [String] The resource path for the request.

@param opts [Hash] An optional Hash of extended options. @option opts [String] :domain Forced override for default domain to use for the request. This

value will also override :sandbox mode on the client.

@since 0.1.0

@return [Request] The Request object instance.

# File lib/twitter-ads/http/request.rb, line 39
def initialize(client, method, resource, opts = {})
  @client   = client
  @method   = method
  @resource = resource
  @options  = opts
  self
end

Public Instance Methods

perform() click to toggle source

Executes the current Request object.

@example

request = Request.new(client, :get, "/#{TwitterAds::API_VERSION}/accounts")
request.perform

@since 0.1.0

@return [Response] The Response object instance generated by the Request.

# File lib/twitter-ads/http/request.rb, line 56
def perform
  handle_error(oauth_request)
end

Private Instance Methods

domain() click to toggle source
# File lib/twitter-ads/http/request.rb, line 62
def domain
  @domain ||= begin
    @options[:domain] || (@client.options[:sandbox] ? SANDBOX_DOMAIN : DEFAULT_DOMAIN)
  end
end
escape_params(input) click to toggle source
# File lib/twitter-ads/http/request.rb, line 110
def escape_params(input)
  input.map do |key, value|
    "#{CGI.escape key.to_s}=#{CGI.escape value.to_s}"
  end.join('&')
end
handle_error(response) click to toggle source
# File lib/twitter-ads/http/request.rb, line 156
def handle_error(response)
  raise TwitterAds::Error.from_response(response) unless response.code < 400
  response
end
http_request() click to toggle source
# File lib/twitter-ads/http/request.rb, line 116
def http_request
  request_url = @resource

  if @options[:params] && !@options[:params].empty?
    request_url += "?#{escape_params(@options[:params])}"
  end

  request      = HTTP_METHOD[@method].new(request_url)
  request.body = @options[:body] if @options[:body]

  @options[:headers]&.each { |header, value| request[header] = value }
  request['user-agent'] = user_agent

  request
end
oauth_request() click to toggle source
# File lib/twitter-ads/http/request.rb, line 68
def oauth_request
  request  = http_request
  consumer = OAuth::Consumer.new(@client.consumer_key, @client.consumer_secret, site: domain)
  token    = OAuth::AccessToken.new(consumer, @client.access_token, @client.access_token_secret)
  request.oauth!(consumer.http, consumer, token)

  handle_rate_limit = @client.options.fetch(:handle_rate_limit, false)
  retry_max         = @client.options.fetch(:retry_max, 0)
  retry_delay       = @client.options.fetch(:retry_delay, 1500)
  retry_on_status   = @client.options.fetch(:retry_on_status, [500, 503])
  retry_count       = 0
  retry_after       = nil

  write_log(request) if @client.options[:trace]
  while retry_count <= retry_max
    response = consumer.http.request(request)
    status_code = response.code.to_i
    break if status_code >= 200 && status_code < 300

    if handle_rate_limit && retry_after.nil?
      rate_limit_reset = response.fetch('x-account-rate-limit-reset', nil) ||
                         response.fetch('x-rate-limit-reset', nil)
      if status_code == 429
        retry_after = rate_limit_reset.to_i - Time.now.to_i
        @client.logger.warn('Request reached Rate Limit: resume in %d seconds' % retry_after)
        sleep(retry_after + 5)
        next
      end
    end

    if retry_max.positive?
      break unless retry_on_status.include?(status_code)
      sleep(retry_delay / 1000)
    end

    retry_count += 1
  end
  write_log(response) if @client.options[:trace]

  Response.new(response.code, response.each {}, response.body)
end
user_agent() click to toggle source
# File lib/twitter-ads/http/request.rb, line 132
def user_agent
  "twitter-ads version: #{TwitterAds::VERSION} " \
  "platform: #{RUBY_ENGINE} #{RUBY_VERSION} (#{RUBY_PLATFORM})"
end
write_log(object) click to toggle source
# File lib/twitter-ads/http/request.rb, line 137
def write_log(object)
  if object.respond_to?(:code)
    @client.logger.info("Status: #{object.code} #{object.message}")
  else
    @client.logger.info("Send: #{object.method} #{domain}#{@resource} #{@options[:params]}")
  end

  object.each { |header| @client.logger.info("Header: #{header}: #{object[header]}") }

  # suppresses body content for non-Ads API domains (eg. upload.twitter.com)
  unless object.body&.empty?
    if @domain == SANDBOX_DOMAIN || @domain == DEFAULT_DOMAIN
      @client.logger.info("Body: #{object.body}")
    else
      @client.logger.info('Body: **OMITTED**')
    end
  end
end