Module: Bone::API::HTTP

Defined in:
lib/bone/api.rb

Constant Summary collapse

SIGVERSION =
'v2'.freeze

Class Attribute Summary collapse

Class Method Summary collapse

Class Attribute Details

.token_suffixObject (readonly)

Returns the value of attribute token_suffix.



120
121
122
# File 'lib/bone/api.rb', line 120

def token_suffix
  @token_suffix
end

Class Method Details

.canonical_host(host) ⇒ Object



176
177
178
179
180
181
182
183
184
185
186
# File 'lib/bone/api.rb', line 176

def canonical_host host
  unless URI === host
    host = host.to_s unless String === host
    host.strip!
    host = "http://#{host}" unless host.match(/^https?:\/\//)
    host = URI.parse(host)
  end
  host.port ||= 80
  host = [host.host.to_s, host.port.to_s].join(':')
  host.downcase
end

.canonical_sig_string(host, meth, path, query, body = nil) ⇒ Object

Builds the canonical string for signing requests. This strips out all ‘&’, ‘?’, and ‘=’ from the query string to be signed. The parameters in the path passed in must already be sorted in case-insensitive alphabetical order and must not be url encoded.

Based on / stolen from: github.com/grempe/amazon-ec2/blob/master/lib/AWS.rb

See also: docs.amazonwebservices.com/AWSEC2/2009-04-04/DeveloperGuide/index.html?using-query-api.html



215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
# File 'lib/bone/api.rb', line 215

def canonical_sig_string host, meth, path, query, body=nil
  # Sort, and encode parameters into a canonical string.
  sorted_params = query.sort {|x,y| x[0].to_s <=> y[0].to_s }
  encoded_params = sorted_params.collect do |p|
    encoded = [Bone.uri_escape(p[0]), Bone.uri_escape(p[1])].join '='
    # Ensure spaces are encoded as '%20', not '+'
    encoded = encoded.gsub '+', '%20'
    # According to RFC3986 (the scheme for values expected 
    # by signing requests), '~' should not be encoded
    encoded = encoded.gsub '%7E', '~'
  end
  querystr = encoded_params.join '&'
  parts = [meth.to_s.downcase, canonical_host(host), path, querystr]
  parts << body unless body.to_s.empty?
  parts.join "\n"
end

.canonical_time(now = Time.now) ⇒ Object



172
173
174
# File 'lib/bone/api.rb', line 172

def canonical_time now=Time.now
  now.utc.to_i
end

.connectObject



166
167
168
169
170
# File 'lib/bone/api.rb', line 166

def connect
  require 'em-http-request'  # TODO: catch error, deregister this API
  @external_em = EM.reactor_running?
  #@retry_delay, @redirects, @max_retries, @performed_retries = 2, 1, 2, 0
end

.destroy(token, secret) ⇒ Object



140
141
142
143
144
145
# File 'lib/bone/api.rb', line 140

def destroy(token, secret)
  query = {}
  path = Bone::API.path('destroy', token)
  ret = http_request token, secret, :delete, path, query
  !ret.nil?  # errors return nil
end

.encode(secret, str, escape = true) ⇒ Object

Encodes the given string with the secret_access_key by taking the hmac-sha1 sum, and then base64 encoding it. Optionally, it will also url encode the result of that to protect the string if it’s going to be used as a query string parameter.

Based on / stolen from: github.com/grempe/amazon-ec2/blob/master/lib/AWS.rb



238
239
240
241
242
# File 'lib/bone/api.rb', line 238

def encode secret, str, escape=true
  digest = OpenSSL::HMAC.digest Bone.digest_type.new, secret.to_s, str.to_s
  b64_hmac = Base64.encode64(digest).tr "\n", ''
  escape ? Bone.uri_escape(b64_hmac) : b64_hmac
end

.generateObject



155
156
157
158
159
# File 'lib/bone/api.rb', line 155

def generate
  path = Bone::API.path('generate')
  ret = http_request '', '', :post, path, {}
  ret.nil? ? nil : ret.split($/)
end

.generate_signature(secret, host, meth, path, query, body = nil) ⇒ Object



258
259
260
261
262
263
# File 'lib/bone/api.rb', line 258

def generate_signature secret, host, meth, path, query, body=nil
  str = canonical_sig_string host, meth, path, query, body
  sig = encode secret, str
  Bone.ld [sig, str, body].inspect
  sig
end

.get(token, secret, name) ⇒ Object

/v2/[name]



122
123
124
125
126
# File 'lib/bone/api.rb', line 122

def get(token, secret, name)
  path = Bone::API.path(token, 'key', name)
  query = {}
  http_request token, secret, :get, path, query
end

.key?(token, secret, name) ⇒ Boolean

Returns:

  • (Boolean)


137
138
139
# File 'lib/bone/api.rb', line 137

def key?(token, secret, name)
  !get(token, secret, name).nil?
end

.keys(token, secret, filter = '*') ⇒ Object



132
133
134
135
136
# File 'lib/bone/api.rb', line 132

def keys(token, secret, filter='*')
  path = Bone::API.path(token, 'keys')
  ret = http_request token, secret, :get, path, {}
  (ret || '').split($/)
end

.parse_query(qs, d = '&;') ⇒ Object

Based on / stolen from: github.com/chneukirchen/rack/blob/master/lib/rack/utils.rb which was based on / stolen from Mongrel



190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
# File 'lib/bone/api.rb', line 190

def parse_query(qs, d = '&;')
  params = {}
  (qs || '').split(/[#{d}] */n).each do |p|
    k, v = p.split('=', 2).map { |x| Bone.uri_unescape(x) }
    if cur = params[k]
      if cur.class == Array
        params[k] << v
      else
        params[k] = [cur, v]
      end
    else
      params[k] = v
    end
  end
  return params
end

.prepare_query(query = {}, token = Bone.token, stamp = canonical_time) ⇒ Object



244
245
246
247
248
249
250
# File 'lib/bone/api.rb', line 244

def prepare_query query={}, token=Bone.token, stamp=canonical_time
  { "sigversion" => Bone::API::HTTP::SIGVERSION,
    "apiversion" => Bone::APIVERSION,
    "token"      => token,
    "stamp"      => stamp
  }.merge query
end

.register(token, secret) ⇒ Object



150
151
152
153
154
# File 'lib/bone/api.rb', line 150

def register(token, secret)
  query = {}
  path = Bone::API.path('register', token)
  http_request token, secret, :post, path, query, secret
end

.secret(token, secret) ⇒ Object



146
147
148
149
# File 'lib/bone/api.rb', line 146

def secret(token, secret)
  path = Bone::API.path(token, 'secret')
  ret = http_request token, secret, :get, path, {}
end

.set(token, secret, name, value) ⇒ Object



127
128
129
130
131
# File 'lib/bone/api.rb', line 127

def set(token, secret, name, value)
  path = Bone::API.path(token, 'key', name)
  query = {}
  http_request token, secret, :post, path, query, value
end

.sign_query(token, secret, meth, path, query, body = nil) ⇒ Object



252
253
254
255
# File 'lib/bone/api.rb', line 252

def sign_query token, secret, meth, path, query, body=nil
  sig = generate_signature secret, Bone.source, meth, path, query, body
  { 'sig' => sig }.merge query
end

.token?(token, secret) ⇒ Boolean

Returns:

  • (Boolean)


160
161
162
163
164
165
# File 'lib/bone/api.rb', line 160

def token?(token, secret)
  path = Bone::API.path(token)
  query = {}
  ret = http_request token, secret, :get, path, query
  !ret.nil?
end