Skip to content

Instantly share code, notes, and snippets.

@cyberhobo
Created December 19, 2016 23:09
Show Gist options
  • Save cyberhobo/12ec1fb84595c74494258a80f531846b to your computer and use it in GitHub Desktop.
Save cyberhobo/12ec1fb84595c74494258a80f531846b to your computer and use it in GitHub Desktop.
Basis for a Ruby Freemius HTTP API client.
module Freemius
API_HOST = 'api.freemius.com'
SANDBOX_HOST = 'sandbox-api.freemius.com'
class Base
# Options taken from http://docs.freemius.apiary.io/#introduction/the-authentication-header
# * host Default is api.freemius.com
# * api_version Default is v1
# * scope_entity Default is 'plugin'. Could also be 'developer', 'install', 'site', 'user'
# * scope_entity_id Required.
# * public_key Required.
# * secret_key Required.
def initialize(options)
Freemius.host = options.fetch(:host) { API_HOST }
Freemius.api_version = options.fetch(:api_version) { 'v1' }
Freemius.scope_entity = options.fetch(:scope_entity) { 'plugin' }
Freemius.scope_entity_id = options.fetch(:scope_entity_id) do
raise ArgumentError.new('Scope entity ID is required to initialize Freemius') if Freemius.scope_entity_id.nil?
end
Freemius.public_key = options.fetch(:public_key) do
raise ArgumentError.new('Public key is required to initialize Freemius') if Freemius.public_key.nil?
end
Freemius.secret_key = options.fetch(:secret_key) do
raise ArgumentError.new('Secret key is required to initialize Freemius') if Freemius.secret_key.nil?
end
end
def base_url
"https://#{Freemius.host}#{base_path}"
end
def base_path
"/#{Freemius.api_version}/#{Freemius.scope_entity.pluralize}/#{Freemius.scope_entity_id}"
end
def submit(method, path, data = {})
body = [:put, :post].include?(method) ? data.to_json : ''
headers = headers(method, "#{base_path}/#{path.split('?').first}", body)
response = http_client.run_request(method, path, body, headers)
JSON.parse(response.body)
end
private
def http_client
@http_client ||= Faraday.new(base_url, :ssl => { :ca_file => ENV['CERT_PATH'], :version => :TLSv1 })
end
def headers(method, path, body)
formatted_date = Time.now.strftime('%a, %e %b %Y %H:%M:%S %z')
content_type = 'application/json'
md5 = body.empty? ? '' : Digest::MD5.hexdigest(body)
signature_content = "#{method.to_s.upcase}\n#{md5}\n#{content_type}\n#{formatted_date}\n#{path}"
digest = OpenSSL::Digest.new('sha256')
signature = base64_url_encode(OpenSSL::HMAC.hexdigest(digest, Freemius.secret_key, signature_content))
{
'Authorization' => "FS #{Freemius.scope_entity_id}:#{Freemius.public_key}:#{signature}",
'Content-Type' => content_type,
'Date' => formatted_date
}
end
def base64_url_encode(data)
Base64::encode64( data ).tr('+/', '-_').gsub('=', '').gsub("\n", '')
end
end
class << self
attr_accessor :host,
:scope_entity,
:scope_entity_id,
:public_key,
:secret_key,
:api_version
def configure
yield self
true
end
alias :config :configure
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment