class ALD::API

Access the ALD API programatically.

Public

↑ top

Attributes

auth[R]

Get current authentication information Hash (see #auth=)

Public Class Methods

new(root_url) click to toggle source

Create a new instance to access an ALD server.

root_url

a String pointing to the root URL of the server's API.

Example

api = ALD::API.new('http://api.my_ald_server.com/v1/')
# File lib/ALD/api.rb, line 22
def initialize(root_url)
  @root_url = URI(root_url)
  @item_store, @user_store = {}, {}
end

Public Instance Methods

auth=(auth) click to toggle source

Set authentication information for future requests.

auth

a Hash containing the authentication information:

:name

the user name to use

:password

the plaintext password to use

Returns

Returns the hash that was passed.

Raises ArgumentError if the passed hash does not have the specified keys.

# File lib/ALD/api.rb, line 39
def auth=(auth)
  raise ArgumentError unless valid_auth?(auth)
  @auth = auth
end
item(*args) click to toggle source

Get an individual item. This method is roughly equivalent to calling ALD::API::Collection#[] on #items. Calling this method might trigger a HTTP request.

Examples

api.item('185d265f24654545aad3f88e8a383339')
api.item('MyApp', '0.9.5')

# unlike ItemCollection#[], this also supports passing a Hash (and a Boolean):
api.item({'id' => '185d265f24654545aad3f88e8a383339',
         'name' => 'MyApp',
         'version' => '4.5.6'})
# However, this last form is only meant to be used internally and should
# never be called by library consumers.

Returns

Returns the ALD::API::Item instance representing the item, or nil if not found.

Raises ArgumentError if the arguments are not of one of the supported forms.

Signature

item(id)
item(name, version)
id

the GUID String of the item to return

name

a String containing the item's name

version

a String containing the item's semver version

# File lib/ALD/api.rb, line 114
def item(*args)
  if args.first.is_a? Hash # used internally to avoid multiple Item instances
    args.first['id'] = normalize_id(args.first['id'])
    @item_store[args.first['id']] ||= Item.new(self, *args)
  elsif args.length == 1 && args.first.is_a?(String) # GUID
    @item_store[normalize_id(args.first)] || items[args.first]
  elsif args.length == 2 # name and version
    items[*args]
  else
    raise ArgumentError
  end
end
items(conditions = nil) click to toggle source

Get a collection of items from this server. This calls ALD::API::Conditioned#where on the collection of all items. This method might trigger a HTTP request.

conditions

a Hash of conditions the items should meet. Valid conditions are documented at ALD::API::Conditioned#where.

Example

api.items.each { |i| puts i.name }
api.items(name: 'MyApp') # equivalent to api.items.where(name: 'MyApp')

Returns

Returns an ALD::API::ItemCollection containing the items.

Raises ArgumentError if the specified conditions are invalid.

# File lib/ALD/api.rb, line 59
def items(conditions = nil)
  @all_items ||= ItemCollection.new(self)
  @all_items.where(conditions)
end
user(*args) click to toggle source

Get an individual user. This method is roughly equivalent to calling ALD::API::Collection#[] on #users. Calling this method might trigger a HTTP request.

Examples

api.user('6a309ac8a4304f5cb1e6a2982f680ca5')
api.user('Bob')

# As #item, this method also supports being passed a Hash (and a Boolean),
# which should only be used internally.

Returns

Returns the ALD::API::User instance representing the user, or nil if not found.

Raises ArgumentError if the arguments are not of one of the supported forms.

Signature

user(id)
user(name)
id

a 32-character GUID string containing the user's ID

name

a String containing the user's name

# File lib/ALD/api.rb, line 151
def user(*args)
  if args.first.is_a? Hash # used internally to avoid multiple User instances
    args.first['id'] = normalize_id(args.first['id'])
    @user_store[args.first['id']] ||= User.new(self, *args)
  elsif args.length == 1 && args.first.is_a?(String)
    @user_store[normalize_id(args.first)] || users[args.first]
  else
    raise ArgumentError
  end
end
users(conditions = nil) click to toggle source

Get a collection of users on this server. This calls ALD::API::Conditioned#where on the collection of all users. This method might trigger a HTTP request.

conditions

a Hash of conditions the users should meet. Valid conditions are documented at ALD::API::Conditioned#where.

Returns

Returns an ALD::API::UserCollection containing the users.

# File lib/ALD/api.rb, line 72
def users(conditions = nil)
  @all_users ||= UserCollection.new(self)
  @all_users.where(conditions)
end
version() click to toggle source

Get the API version supported by the server. This method triggers a HTTP request.

Returns

Returns the semver version string of the API.

# File lib/ALD/api.rb, line 81
def version
  @version ||= request('/version')['version']
end

Internal

↑ top

Constants

DEFAULT_HEADERS

The default headers to be used in #request.

Public Instance Methods

normalize_id(id) click to toggle source

Given a GUID string, bring it into a standardized form. This is used internally to make comparing GUIDs easier.

id

the GUID String to normalize

Returns

Returns the normalized GUID String.

# File lib/ALD/api.rb, line 168
def normalize_id(id)
  id.upcase.gsub(/[^0-9A-F]/, '')
end
request(url, method = :get, headers = {}, body = nil) click to toggle source

Make a raw request to the ALD server. This is used internally, and library consumers should only call it if they are familiar with the ALD API.

url

the URL String, relative to the root URL, to request against.

method

a Symbol indicating the HTTP method to use. Supported: :get, :post

headers

a Hash containing additional headers (for the defaults see ::DEFAULT_HEADERS).

body

If method is :post, a request body to use.

Returns

Returns The response body; as Hash / Array if the 'Content-type' header indicates a JSON response; as raw String otherwise.

Raises ArgumentError is method is not supported.

Raises API::RequestError if the response code is not in (200…300).

# File lib/ALD/api.rb, line 193
def request(url, method = :get, headers = {}, body = nil)
  Net::HTTP.start(@root_url.host, @root_url.port) do |http|
    url = @root_url + url

    request = create_request(method, url)
    DEFAULT_HEADERS.merge(headers).each do |k, v|
      request[k] = v
    end

    response = http.request(request)
    response = request_with_auth(http, request, url, response) if response.code.to_i == 401

    raise RequestError unless (200...300).include?(response.code.to_i)
    if response['Content-type'].include?('application/json')
      JSON.parse(response.body)
    else
      response.body
    end
  end
end

Private Instance Methods

auth_method(response) click to toggle source

Get the authentication method used by a server

response

the Net::HTTPResponse to examine

Returns

Returns the used method as Symbol, e.g. :digest or :basic

# File lib/ALD/api.rb, line 272
def auth_method(response)
  response['WWW-Authenticate'].strip.split(' ')[0].downcase.to_sym
end
create_request(method, url) click to toggle source

Create a new Net::HTTPRequest for the given method.

method

a Symbol indicating the HTTP verb (lowercase

url

the URI to request

Returns

Returns a Net::HTTPRequest for the given method.

Raises ArgumentError if the verb is not supported.

# File lib/ALD/api.rb, line 224
def create_request(method, url)
  case method
    when :get
      Net::HTTP::Get.new url.request_uri
    when :post
      Net::HTTP::Post.new url.request_uri
    else
      raise ArgumentError
  end
end
request_with_auth(http, request, url, failed_response) click to toggle source

Retry a request with authentication

http

a Net::HTTP object to use for the request

request

the Net::HTTPRequest to use

url

the URI that is requested

failed_response

the response that was given when requesting without auth

Returns

Returns a successful Net::HTTPResponse for the request.

Raises NoAuthError if @auth is not set.

Raises UnsupportedAuthMethodError if the server uses a not supported auth method.

Raises InvalidAuthError if the authenticated request yields a 401 response.

# File lib/ALD/api.rb, line 250
def request_with_auth(http, request, url, failed_response)
  raise NoAuthError if @auth.nil?
  case auth_method(failed_response)
    when :basic
      request.basic_auth(@auth[:name], @auth[:password])
    when :digest
      url.user, url.password = @auth[:name], @auth[:password]
      request.add_field 'Authorization', Net::HTTP::DigestAuth.new.auth_header(url, failed_response['WWW-Authenticate'], request.method)
    else
      raise UnsupportedAuthMethodError
  end

  response = http.request(request)
  raise InvalidAuthError if response.code.to_i == 401
  response
end
valid_auth?(auth) click to toggle source

Check if a Hash contains valid auth data

auth

the Hash to check

Returns

Returns true, if the Hash contains the necessary keys, false otherwise.

# File lib/ALD/api.rb, line 281
def valid_auth?(auth)
  auth.is_a?(Hash) && %w[name password].all? { |k| auth.key?(k.to_sym) }
end