class Vox::HTTP::Client

HTTP Client for interacting with the REST portion of the Discord API

Constants

API_BASE

Base URL to base endpoints off of.

API_VERSION

Discord REST API version.

DEFAULT_HEADERS

Headers that form the base for every request.

Attributes

conn[R]

@!visibility private

Public Class Methods

new(token) { |conn| ... } click to toggle source
# File lib/vox/http/client.rb, line 46
def initialize(token)
  @conn = default_connection
  @conn.authorization('Bot', token.delete_prefix('Bot '))
  yield(@conn) if block_given?
end

Public Instance Methods

inspect() click to toggle source

@!visibility private Hide the big instance variables

# File lib/vox/http/client.rb, line 82
def inspect
  "#<Vox::HTTP::Client:0x#{object_id.to_s(16).rjust(16, '0')}>"
end
request(route, query: nil, data: nil, json: nil, raw: nil, reason: nil) click to toggle source

Run a request @param query [Hash<String, String>, nil] Query string parameters. @param data [Hash<(String, Integer), (String, content_type)>, String, nil] HTTP body for non-JSON payloads. @param json [Hash, nil] Object that will be serialized to JSON for requests. @param raw [true, false] Whether or not the response body should be parsed from

JSON.

@param reason [String, nil] Reason for use in paths that support audit log reasons. @return [Hash, nil] The response body serialized to a Hash, or nil when a route returns 204.

# File lib/vox/http/client.rb, line 60
def request(route, query: nil, data: nil, json: nil, raw: nil, reason: nil)
  req = @conn.build_request(route.verb) do |r|
    setup_basic_request(r, route, query: query, reason: reason)

    if json
      r.body = MultiJson.dump(json)
      r.headers['Content-Type'] = 'application/json'
    elsif data
      r.body = data
    end
  end

  begin
    resp = @conn.builder.build_response(@conn, req)
    handle_response(resp, raw, req.options.context[:trace])
  rescue Error::TooManyRequests
    retry
  end
end

Private Instance Methods

default_connection() click to toggle source

A default connection used when you're not passing your own @return [Faraday::Connection]

# File lib/vox/http/client.rb, line 126
def default_connection
  Faraday.new(url: API_BASE, headers: DEFAULT_HEADERS) do |faraday|
    faraday.use :vox_ratelimiter
    faraday.request :multipart
    faraday.response(
      :logger,
      Logging.logger['Vox::HTTP'],
      { formatter: Vox::HTTP::Middleware::LogFormatter }
    )
  end
end
handle_response(resp, raw, req_id) click to toggle source

@param resp [Faraday::Response] The response to be processed.

# File lib/vox/http/client.rb, line 100
def handle_response(resp, raw, req_id)
  raise Error::ServerError.new(req_id) if (500..600).cover? resp.status

  data = raw ? resp.body : MultiJson.load(resp.body, symbolize_keys: true)
  case resp.status
  when 204, 304
    nil
  when 200..300
    data
  when 400
    raise Error::BadRequest.new(data, req_id)
  when 401
    raise Error::Unauthorized.new(data, req_id)
  when 403
    raise Error::Forbidden.new(data, req_id)
  when 404
    raise Error::NotFound.new(data, req_id)
  when 405
    raise Error::MethodNotAllowed.new(data, req_id)
  when 429
    raise Error::TooManyRequests.new(data, req_id)
  end
end
setup_basic_request(req, route, query: nil, reason: nil) click to toggle source

@param req [Faraday::Request] Request to be executed @param route [Vox::HTTP::Route] @param query [Hash<String, String>, nil] @param reason [String, nil]

# File lib/vox/http/client.rb, line 92
def setup_basic_request(req, route, query: nil, reason: nil)
  req.path = route.format.delete_prefix('/')
  req.params = query unless query.nil? || query.empty?
  req.headers['X-Audit-Log-Reason'] = reason if reason
  req.options.context = { rl_key: route.rl_key, trace: SecureRandom.alphanumeric(6) }
end