class Hoodoo::Client
Hoodoo::Client
provides a high-level abstracted interface for making calls to Resource implementations. A Client
instance is created and used as a factory for objects representing individual Resources. Callers use a consistent, high level interface in these objects to make requests to those Resources and do not usually need to worry about where implementations are, or how they are being contacted.
Please see the constructor documentation for full details.
Public Class Methods
Create a client instance. This is used as a factory for endpoint instances which communicate with Resource implementations.
Overview¶ ↑
Suppose you have Resources with only public_actions
so that no sessions are needed, with resource implementations running at host “test.com” on paths which follow downcase/pluralisation conventions. In this case, creating a Client
instance can be as simple as:
client = Hoodoo::Client.new( base_uri: 'http://test.com/', auto_session: false )
Ask this client for an endpoint of Resource “Member” implementing version 2 of its interface:
members = client.resource( :Member, 2 )
Perform operations on the endpoints according to the methods in the base class - see these for details:
The above reference describes the basic approach for each call, with common parameters such as the query hash or body hash data described in the base class constructor, Hoodoo::Client::Endpoint#new.
As an example, we could list records 50-79 inclusive of “Member” sorted by created_at
ascending, embedding an “account” for each, where field ‘surname’ matches ‘Smith’ - assuming there’s an implementation of such a Resource interface available! - as follows:
results = members.list( offset: 50, limit: 25, sort: 'created_at', direction: 'asc', search: { 'surname' => 'Smith' }, _embed: 'account' )
This will return a Hoodoo::Client::AugmentedArray
. This is an Array subclass which will contain the (up to) 25 results from the above call and supports Hoodoo::Client::AugmentedArray#dataset_size
which (if the called Resource endpoint implementation provides the information) gives the total size of the data set at the time of calling. Hoodoo::Client::AugmentedArray#estimated_dataset_size
likewise gives access to the estimated count, if available.
The other 4 methods return a Hoodoo::Client::AugmentedHash
. This is a Hash subclass. Both the Array and Hash subclasses provide a common standard way to handle errors. See the documentation of these classes for details; in brief, you must always check for errors before examining the Hash or Array data with a pattern such as this:
if results.platform_errors.has_errors? # Examine results.platform_errors, which is a # Hoodoo::Errors instance, and deal with the contents. else # Treat 'results' as a Hash containing the Resource # data (String keys) or Array of Hashes of such data. end
Session management¶ ↑
By default, the Hoodoo::Client
constructor assumes you want automatic session management.
If you want to use automatic sessions, a Resource endpoint which implements the Session Resource interface is required. This must accept a POST (create
) action with a payload of two JSON fields: caller_id
and authentication_secret
. It must return a Resource with an “id” value that contains the session ID to quote in future requests via the X-Session-ID HTTP header; or it should return an error if the Caller ID and/or authentication secret are incorrect.
The Resource is assumed to live at the same base URI and/or be discovered by the same mechanism (e.g. by convention) as everything else you’ll use the client instance for. For more about discovery related paramters, see later.
You will need to provide the caller_id
and authentication_secret
(as named parameter caller_secret
) to the constructor. If the name of the Resource implementing the Session interface is not ‘Session’, or not at version 1, then you can also provide alternatives. For example, suppose we want to use automatic session management for Caller ID “0123” and secret “ABCD” via version 2 of “CustomSession”:
client = Hoodoo::Client.new( base_uri: 'http://test.com/', auto_session_resource: 'CustomSession', auto_session_version: 2, caller_id: '0123', caller_secret: 'ABCD' )
Finally, you can manually supply a session ID externally for the X-Session-ID header through the session_id
parameter. This may be used in conjunction with auto-session management; in that case, the given session is used until it expires (a “platform.invalid_session” error is encountered), after which a new one will be obtained.
Discovery parameters¶ ↑
The Client
instance needs to be able to find the place where the requested Resource implementations are located, which it does using the Hoodoo::Services::Discovery
framework. You should read the description of this framework to get a feel for how that works first.
One of the following named parameters must be supplied in order to choose a discovery engine for finding Resource endpoints:
discoverer
-
The
Client
needs a Discoverer to map from resource names and versions to locations on the Internet of the actual resource endpoint implementation. Via thediscoverer
parameter, you can explicitly pass aHoodoo::Services::Discovery
subclass instance customised to your own requirements. There are also convenience parameters available - see below - that create discoverer instances for you, covering common use cases. If provided, thediscoverer
parameter takes precedence over any other parameters below. base_uri
-
When given, Resource discovery is done by
Hoodoo::Services::Discovery::ByConvention
. The path that the by-convention discoverer creates is appended to the base URI to build the full URI at which a server implementing each requested Resource endpoint must be listening (else a 404 / ‘platform.not_found’ response arises). Specify as a String. If provided, thebase_uri
parameter takes precedence over any other parameters below. drb_uri
-
When given, Resource discovery is done by
Hoodoo::Services::Discovery::ByDRb
. A DRb service providing discovery data must be running at the given URI. Specify as a String. SeeHoodoo::Services::Discovery::ByDRb::DRbServer
and filedrb_server_start.rb
for more. drb_port
-
Instead of
drb_uri
, you can provide the port number of a DRb server on localhost. SeeHoodoo::Services::Discovery::ByDRb
for which ofdrb_uri
ordrb_port
take precedence, if both are provided.
As an example of using a custom Discoverer, consider a simple HTTP case with the base_uri
parameter. The default “by convention” discoverer pluralises all paths, but let’s say you have exceptions for Version and Health singleton resources which you’ve elected to place on singular, not plural, paths. You will need to construct a custom discoverer with these exceptions. See the documentation for Hoodoo::Services::Discovery::ByConvention
to understand the options passed in for the custom routing information.
base_uri = 'https://api.test.com/' discoverer = Hoodoo::Services::Discovery::ByConvention.new( :base_uri => base_uri, :routing => { :Version => { 1 => '/v1/version' }, :Health => { 1 => '/v1/health' } } ) client = Hoodoo::Client.new( :discoverer => discoverer, # ...other options... )
Other parameters¶ ↑
The following additional named parameters are all optional:
locale
-
The String given in Content-Language and Accept-Language HTTP headers for requests; default is “en-nz”.
session_id
-
An optional session ID to be used for the initial X-Session-ID request header value.
auto_session
-
If
false
, automatic session management is disabled. Default istrue
. auto_session_resource
-
Name of the Resource to use for automatic session management as a String or Symbol. Default is +“Session”+.
auto_session_version
-
Version of the Resource to use for automatic session management as an Integer. Default is 1.
caller_id
-
If using automatic session management, a Caller
UUID
must be provided. It is used as thecaller_id
field’s value in the POST (create
) call to the session Resource endpoint. caller_secret
-
If using automatic session management, a Caller authentication secret must be provide. It is used as the
authentication_secret
field’s value in the POST (create
) call to the session Resource endpoint.
If curious about the implementation details of automatic session management, see the Hoodoo::Client::Endpoints::AutoSession class’s code.
# File lib/hoodoo/client/client.rb, line 242 def initialize( base_uri: nil, drb_uri: nil, drb_port: nil, discoverer: nil, locale: nil, session_id: nil, auto_session: :true, auto_session_resource: 'Session', auto_session_version: 1, caller_id: nil, caller_secret: nil ) @base_uri = base_uri @drb_uri = drb_uri @drb_port = drb_port @locale = locale @discoverer = if discoverer != nil discoverer elsif @base_uri != nil if defined?( Hoodoo::Services::Discovery::ByConvention ) Hoodoo::Services::Discovery::ByConvention.new( :base_uri => @base_uri ) else raise 'Hoodoo::Client: The constructor parameters indicate the use of a "by convention" discoverer. This discoverer requires ActiveSupport; ensure the ActiveSupport gem is present and "require"-able.' end elsif @drb_uri != nil || @drb_port != nil Hoodoo::Services::Discovery::ByDRb.new( :drb_uri => @drb_uri, :drb_port => @drb_port ) else raise 'Hoodoo::Client: Please pass one of the "discoverer", "base_uri", "drb_uri" or "drb_port" parameters.' end # If doing automatic sessions, acquire a session creation endpoint @session_id = session_id @caller_id = caller_id @caller_secret = caller_secret if auto_session @auto_session_endpoint = Hoodoo::Client::Endpoint.endpoint_for( auto_session_resource, auto_session_version, { :discoverer => @discoverer } ) end end
Public Instance Methods
Alias of resource
, as syntax sugar for those who prefer to think of the return value as an endpoint that is used to contact a resource, rather than a remote abstraction of the resource as an entity.
Get an endpoint instance which you can use for talking to a Resource. See the constructor for full information.
You’ll always get an endpoint instance back from this call. If an implementation of the given version of the given Resource cannot be contacted, you will only get a 404 (‘platform.not_found’) or 408 (‘platform.timeout’) response when you try to make a call to it.
resource
-
Resource name as a Symbol or String (e.g.
:Purchase
). version
-
Endpoint
version as an Integer; optional; default is 1. options
-
Optional options Hash (see below).
The options Hash key/values are as follows:
locale
-
Locale string for request/response, e.g. “en-gb”. Optional. If omitted, defaults to the locale set in this
Client
instance’s constructor. - OTHERS
-
See
Hoodoo::Client::Headers
‘HEADER_TO_PROPERTY
. All such option keys MUST be Symbols.
# File lib/hoodoo/client/client.rb, line 319 def resource( resource, version = 1, options = {} ) endpoint_options = { :discoverer => @discoverer, :session_id => @session_id, :locale => options[ :locale ] || @locale } Hoodoo::Client::Headers::HEADER_TO_PROPERTY.each do | rack_header, description | property = description[ :property ] endpoint_options[ property ] = options[ property ] if options.has_key?( property ) end endpoint = Hoodoo::Client::Endpoint.endpoint_for( resource, version, endpoint_options ) unless @auto_session_endpoint.nil? remote_discovery_result = Hoodoo::Services::Discovery::ForRemote.new( :resource => resource, :version => version, :wrapped_endpoint => endpoint ) endpoint = Hoodoo::Client::Endpoint::AutoSession.new( resource, version, :caller_id => @caller_id, :caller_secret => @caller_secret, :session_endpoint => @auto_session_endpoint, :discovery_result => remote_discovery_result ) end return endpoint end