class Tml::Api::Client
Constants
- API_PATH
Public Class Methods
error?(data)
click to toggle source
checks if there are any API errors
# File lib/tml/api/client.rb, line 68 def self.error?(data) not data['error'].nil? end
Public Instance Methods
access_token()
click to toggle source
access token
# File lib/tml/api/client.rb, line 203 def access_token application.token end
api(path, params = {}, opts = {})
click to toggle source
checks mode and cache, and fetches data
# File lib/tml/api/client.rb, line 226 def api(path, params = {}, opts = {}) # inline mode should always use API calls if live_api_request? params = params.merge(:access_token => access_token, :app_id => application.key) return process_response(execute_request(path, params, opts), opts) end return unless cache_enabled?(opts) # ensure the cache version is not outdated verify_cache_version return if Tml.cache.version.invalid? # get request uses local cache, then CDN data = Tml.cache.fetch(opts[:cache_key]) do fetched_data = get_from_cdn(opts[:cache_key]) unless Tml.cache.read_only? fetched_data || {} end process_response(data, opts) end
api_host()
click to toggle source
API Host
# File lib/tml/api/client.rb, line 77 def api_host @api_host ||= begin uri = api_uri.dup uri.path = '' uri.query = nil uri.to_s end end
api_uri()
click to toggle source
# File lib/tml/api/client.rb, line 72 def api_uri @api_uri ||= URI::parse(application.host) end
cache_enabled?(opts)
click to toggle source
checks if cache is enable
# File lib/tml/api/client.rb, line 217 def cache_enabled?(opts) # only gets ever get cached return false unless opts[:method] == :get return false if opts[:cache_key].nil? return false unless Tml.cache.enabled? true end
cdn_connection()
click to toggle source
# File lib/tml/api/client.rb, line 147 def cdn_connection @cdn_connection ||= Faraday.new(:url => cdn_host) do |faraday| faraday.request(:url_encoded) # form-encode POST params faraday.adapter(Faraday.default_adapter) # make requests with Net::HTTP end end
cdn_host()
click to toggle source
# File lib/tml/api/client.rb, line 122 def cdn_host @cdn_host ||= URI.join(application.cdn_host, '/').to_s end
cdn_uri()
click to toggle source
# File lib/tml/api/client.rb, line 126 def cdn_uri @cdn_host ||= URI::parse(application.cdn_host) end
connection()
click to toggle source
API connection
# File lib/tml/api/client.rb, line 87 def connection @connection ||= Faraday.new(:url => api_host) do |faraday| faraday.request(:url_encoded) # form-encode POST params # faraday.response :logger # log requests to STDOUT faraday.adapter(Faraday.default_adapter) # make requests with Net::HTTP end end
decompress_data(compressed_data)
click to toggle source
# File lib/tml/api/client.rb, line 154 def decompress_data(compressed_data) data = Zlib::GzipReader.new(StringIO.new(compressed_data.to_s)).read Tml.logger.debug("Compressed: #{compressed_data.length} Uncompressed: #{data.length}") data rescue => ex Tml.logger.error("Failed to decompress data: #{ex.message[0..255]}") compressed_data end
delete(path, params = {}, opts = {})
click to toggle source
delete from API
# File lib/tml/api/client.rb, line 63 def delete(path, params = {}, opts = {}) api(path, params, opts.merge(:method => :delete)) end
execute_request(path, params = {}, opts = {})
click to toggle source
execute API request
# File lib/tml/api/client.rb, line 305 def execute_request(path, params = {}, opts = {}) response = nil error = nil path = prepare_api_path(path) opts[:method] ||= :get trace_api_call(path, params, opts.merge(:host => api_host)) do begin if opts[:method] == :post response = connection.post(path, params) elsif opts[:method] == :put response = connection.put(path, params) elsif opts[:method] == :delete response = connection.delete(path, params) else response = connection.get do |request| prepare_request(request, path, params, opts) end end rescue => ex Tml.logger.error("Failed to execute request: #{ex.message[0..255]}") error = ex nil end end if error raise Tml::Exception.new("Error: #{error}") end if response.status >= 500 && response.status < 600 raise Tml::Exception.new("Error: #{response.body}") end data = response.body if opts[:method] == :get && !opts[:uncompressed] return if data.nil? or data == '' unless opts[:uncompressed] data = decompress_data(data) end end return data if opts[:raw] begin data = JSON.parse(data) rescue => ex raise Tml::Exception.new("Failed to parse response: #{ex.message[0..255]}") end if data.is_a?(Hash) and not data['error'].nil? raise Tml::Exception.new("Error: #{data['error']}") end data end
get(path, params = {}, opts = {})
click to toggle source
get from API
# File lib/tml/api/client.rb, line 48 def get(path, params = {}, opts = {}) api(path, params, opts.merge(:method => :get)) end
get_cache_version()
click to toggle source
get cache version from CDN
# File lib/tml/api/client.rb, line 96 def get_cache_version data = get_from_cdn('version', {t: Time.now.to_i}, {public: true, uncompressed: true}) unless data Tml.logger.debug('No releases have been published yet') return '0' end data['version'] end
get_cdn_path(key, opts = {})
click to toggle source
# File lib/tml/api/client.rb, line 130 def get_cdn_path(key, opts = {}) base_path = URI(application.cdn_host).path # Remove usage of String#last for clients who do not use ActiveSupport base_path += '/' unless base_path.size > 0 && base_path[-1..-1] == '/' adjusted_path = "#{base_path}#{application.key}/" if key == 'version' adjusted_path += "#{key}.json" else adjusted_path += "#{Tml.cache.version.to_s}/#{key}.json#{opts[:uncompressed] ? '' : '.gz'}" end adjusted_path end
get_from_cdn(key, params = {}, opts = {})
click to toggle source
get from the CDN
# File lib/tml/api/client.rb, line 164 def get_from_cdn(key, params = {}, opts = {}) if Tml.cache.version.invalid? and key != 'version' return nil end response = nil cdn_path = get_cdn_path(key, opts) trace_api_call(cdn_path, params, opts.merge(:host => cdn_host)) do begin response = cdn_connection.get do |request| prepare_request(request, cdn_path, params, opts) end rescue => ex Tml.logger.error("Failed to execute request: #{ex.message[0..255]}") return nil end end return if response.status >= 500 and response.status < 600 return if response.body.nil? or response.body == '' or response.body.match(/xml/) data = response.body return if data.nil? or data == '' unless opts[:uncompressed] data = decompress_data(data) end begin data = JSON.parse(data) rescue => ex Tml.logger.error("Failed to parse response: #{ex.message[0..255]}") return nil end data end
join_uri(*string)
click to toggle source
# File lib/tml/api/client.rb, line 270 def join_uri(*string) string.join('/').gsub(/\/+/, '/') end
live_api_request?()
click to toggle source
should the API go to live server
# File lib/tml/api/client.rb, line 208 def live_api_request? # if no access token, never use live mode return false if access_token.nil? # if block is specifically asking for it or inline mode is activated Tml.session.inline_mode? or Tml.session.block_option(:live) end
object_class(opts)
click to toggle source
get object class from options
# File lib/tml/api/client.rb, line 367 def object_class(opts) return unless opts[:class] opts[:class].is_a?(String) ? opts[:class].constantize : opts[:class] end
paginate(path, params = {}, opts = {}) { |result| ... }
click to toggle source
paginates through API results
# File lib/tml/api/client.rb, line 250 def paginate(path, params = {}, opts = {}) data = get(path, params, opts.merge({'raw' => true})) while data if data['results'].is_a?(Array) data['results'].each do |result| yield(result) end else yield(data['results']) end if data['pagination'] and data['pagination']['links']['next'] data = get(data['pagination']['links']['next'], {}, opts.merge({'raw' => true})) else data = nil end end end
post(path, params = {}, opts = {})
click to toggle source
post to API
# File lib/tml/api/client.rb, line 53 def post(path, params = {}, opts = {}) api(path, params, opts.merge(:method => :post)) end
prepare_api_path(path)
click to toggle source
prepares API path
# File lib/tml/api/client.rb, line 275 def prepare_api_path(path) return path if path.match(/^https?:\/\//) clean_path = trim_prepending_slash(path) if clean_path.index('v1') == 0 || clean_path.index('v2') == 0 join_uri(api_uri.path, clean_path) else join_uri(api_uri.path, API_PATH, clean_path) end end
prepare_request(request, path, params, opts = {})
click to toggle source
prepares request
# File lib/tml/api/client.rb, line 291 def prepare_request(request, path, params, opts = {}) request.options.timeout = Tml.config.api_client[:timeout] request.options.open_timeout = Tml.config.api_client[:open_timeout] request.headers['User-Agent'] = "tml-ruby v#{Tml::VERSION} (Faraday v#{Faraday::VERSION})" request.headers['Accept'] = 'application/json' unless opts[:uncompressed] request.headers['Accept-Encoding'] = 'gzip, deflate' end request.url(path, params) end
process_response(data, opts)
click to toggle source
process API response
# File lib/tml/api/client.rb, line 373 def process_response(data, opts) return nil if data.nil? return data if opts[:raw] or opts[:raw_json] if data.is_a?(Hash) and data['results'] #Tml.logger.debug("received #{data['results'].size} result(s)") return data['results'] unless object_class(opts) objects = [] data['results'].each do |data| objects << object_class(opts).new(data.merge(opts[:attributes] || {})) end return objects end return data unless object_class(opts) object_class(opts).new(data.merge(opts[:attributes] || {})) end
put(path, params = {}, opts = {})
click to toggle source
put to API
# File lib/tml/api/client.rb, line 58 def put(path, params = {}, opts = {}) api(path, params, opts.merge(:method => :put)) end
results(path, params = {}, opts = {})
click to toggle source
get results from API
# File lib/tml/api/client.rb, line 43 def results(path, params = {}, opts = {}) get(path, params, opts)['results'] end
to_query(hash)
click to toggle source
convert params to query
# File lib/tml/api/client.rb, line 392 def to_query(hash) query = [] hash.each do |key, value| query << "#{key.to_s}=#{value.to_s}" end query.join('&') end
trace_api_call(path, params, opts = {}) { || ... }
click to toggle source
trace api call for logging
# File lib/tml/api/client.rb, line 401 def trace_api_call(path, params, opts = {}) if Tml.config.logger[:secure] [:access_token].each do |param| params = params.merge(param => "##filtered##") if params[param] end end path = "#{path[0] == '/' ? '' : '/'}#{path}" if opts[:method] == :post Tml.logger.debug("post: #{opts[:host]}#{path}") else if params.any? Tml.logger.debug("get: #{opts[:host]}#{path}?#{to_query(params)}") else Tml.logger.debug("get: #{opts[:host]}#{path}") end end t0 = Time.now if block_given? ret = yield end t1 = Time.now Tml.logger.debug("call took #{t1 - t0} seconds") ret end
trim_prepending_slash(str)
click to toggle source
# File lib/tml/api/client.rb, line 286 def trim_prepending_slash(str) str.index('/') == 0 ? str[1..-1] : str end
verify_cache_version()
click to toggle source
verify cache version
# File lib/tml/api/client.rb, line 108 def verify_cache_version return if Tml.cache.version.defined? current_version = Tml.cache.version.fetch if current_version == 'undefined' Tml.cache.version.store(get_cache_version) else Tml.cache.version.set(current_version) end Tml.logger.info("Cache Version: #{Tml.cache.version}") end