class BlizzardApi::Request
Simplifies the requests to Blizzard APIS
Constants
- BASE_URLS
Common endpoints
- CACHE_DAY
One day cache
- CACHE_HOUR
One hour cache
- CACHE_TRIMESTER
Three (commercial) months cache
Attributes
mode[RW]
@!attribute mode
@return [:regular, :extended]
region[RW]
@!attribute region
@return [String] Api region
Public Class Methods
new(region = nil, mode = :regular)
click to toggle source
@!macro regions
# File lib/blizzard_api/request.rb, line 66 def initialize(region = nil, mode = :regular) self.region = region || BlizzardApi.region @redis = Redis.new(host: BlizzardApi.redis_host, port: BlizzardApi.redis_port) if BlizzardApi.use_cache # Use the shared access_token, or create one if it doesn't exists. This avoids unnecessary calls to create tokens. @access_token = BlizzardApi.access_token || create_access_token # Mode @mode = mode end
Protected Instance Methods
api_request(uri, **query_string)
click to toggle source
# File lib/blizzard_api/request.rb, line 154 def api_request(uri, **query_string) # List of request options options_key = %i[ignore_cache ttl format access_token namespace classic classic1x headers since] # Separates request options from api fields and options. Any user-defined option will be treated as api field. options = query_string.select { |k, _v| query_string.delete(k) || true if options_key.include? k } # Namespace query_string[:namespace] = endpoint_namespace(options) if options.include? :namespace # In case uri already have query string parameters joins them with & if query_string.size.positive? query_string = URI.encode_www_form(query_string, false) uri = uri.include?('?') ? "#{uri}&#{query_string}" : "#{uri}?#{query_string}" end request uri, **options end
base_url(scope)
click to toggle source
# File lib/blizzard_api/request.rb, line 82 def base_url(scope) raise ArgumentError, 'Invalid scope' unless BASE_URLS.include? scope format BASE_URLS[scope], region, @game end
create_access_token()
click to toggle source
# File lib/blizzard_api/request.rb, line 120 def create_access_token uri = URI.parse("https://#{BlizzardApi.region}.battle.net/oauth/token") http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true request = Net::HTTP::Post.new(uri.path) request.basic_auth(BlizzardApi.app_id, BlizzardApi.app_secret) request['Content-Type'] = 'application/x-www-form-urlencoded' request.set_form_data grant_type: 'client_credentials' response = http.request(request) BlizzardApi.access_token = JSON.parse(response.body)['access_token'] end
endpoint_namespace(options)
click to toggle source
Returns a valid namespace string for consuming the api endpoints
@param [Hash] options A hash containing the namespace key
# File lib/blizzard_api/request.rb, line 106 def endpoint_namespace(options) version = endpoint_version(options) case options[:namespace] when :dynamic "dynamic-#{version}#{region}" when :static "static-#{version}#{region}" when :profile "profile-#{region}" else raise ArgumentError, 'Invalid namespace scope' end end
endpoint_version(options)
click to toggle source
Returns a valid version namespace
@param [Hash] options A hash containing a valid namespace key
# File lib/blizzard_api/request.rb, line 92 def endpoint_version(options) if options.key? :classic 'classic-' elsif options.key? :classic1x 'classic1x-' else '' end end
request(url, **options)
click to toggle source
# File lib/blizzard_api/request.rb, line 135 def request(url, **options) # Creates the whole url for request parsed_url = URI.parse(url) data = using_cache?(options) ? find_in_cache(parsed_url.to_s) : nil # If data was found that means cache is enabled and valid return JSON.parse(data, symbolize_names: true) if data response = consume_api parsed_url, **options save_in_cache parsed_url.to_s, response.body, options[:ttl] || CACHE_DAY if using_cache? options response_data = response.code.to_i.eql?(304) ? nil : JSON.parse(response.body, symbolize_names: true) return [response, response_data] if mode.eql? :extended response_data end
Private Instance Methods
add_headers(request, options)
click to toggle source
# File lib/blizzard_api/request.rb, line 199 def add_headers(request, options) # Blizzard API documentation states the preferred way to send the access_token is using Bearer token on header request['Authorization'] = "Bearer #{options.fetch(:access_token, @access_token)}" # Format If-modified-since option request['If-Modified-Since'] = options[:since].httpdate if options.key? :since options[:headers]&.each { |header, content| request[header] = content } end
consume_api(url, **options)
click to toggle source
# File lib/blizzard_api/request.rb, line 183 def consume_api(url, **options) # Creates a HTTP connection and request to ensure thread safety http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Get.new(url) add_headers request, options # Executes the request http.request(request).tap do |response| if mode.eql?(:regular) && ![200, 304].include?(response.code.to_i) raise BlizzardApi::ApiException.new "Request failed with code '#{response.code}' details: #{response.to_hash}", response.code.to_i end end end
find_in_cache(resource_url)
click to toggle source
# File lib/blizzard_api/request.rb, line 211 def find_in_cache(resource_url) return false unless BlizzardApi.use_cache @redis.get resource_url if @redis.exists? resource_url end
save_in_cache(resource_url, data, ttl)
click to toggle source
# File lib/blizzard_api/request.rb, line 207 def save_in_cache(resource_url, data, ttl) @redis.setex resource_url, ttl, data if BlizzardApi.use_cache end
using_cache?(options)
click to toggle source
@param options [Hash] Request
options
# File lib/blizzard_api/request.rb, line 177 def using_cache?(options) return false if mode.eql?(:extended) || options.key?(:since) !options.fetch(:ignore_cache, false) end