Deprecated.
NAME
Clustericious::Client - Construct command line and perl clients for RESTful services.
VERSION
version 1.29
SYNOPSIS
tracks.pm :
package Tracks;
use Clustericious::Client;
route 'mixes' => '/mixes.json';
route_doc mixes => 'Get a list of mixes.';
route_args mixes => [
{ name => 'api_key', type => '=s', modifies_url => "query", required => 1 },
{ name => 'per_page',type => '=i', modifies_url => "query", },
{ name => 'tags', type => '=s', modifies_url => "query" },
];
# a 'mixes' method will be constructed automatically.
# a 'mixes' command line parameter will be recognized automatically.
route 'play' => '/play.json';
route_args play => [
{ name => 'token', type => '=s', modifies_url => 'query', required => 1 }
];
sub play {
my $c = shift;
my %args = $c->meta_for->process_args(@_);
# do something with $args{token}
}
# A 'play' command line parameter will call the above method.
tracks.pl :
use lib '.';
use Log::Log4perl qw/:easy/;
Log::Log4perl->easy_init($TRACE);
use tracks;
my $t = Tracks->new(server_url => 'http://8tracks.com' );
my $mixes = $t->mixes(
tags => 'jazz',
api_key => $api_key,
per_page => 2,
) or die $t->errorstring;
print "Mix : $_->{name}\n" for @{ $mixes->{mixes} };
tracks_cli :
use lib '.';
use Clustericious::Client::Command;
use tracks;
use Log::Log4perl qw/:easy/;
Log::Log4perl->easy_init($TRACE);
Clustericious::Client::Command->run(Tracks->new, @ARGV);
~/etc/Tracks.conf :
---
url : 'http://8tracks.com'
From the command line :
$ perl tracks.pl
$ tracks_cli mixes --api_key foo --tags jazz
DESCRIPTION
Clustericious::Client is library for construction clients for RESTful services. It provides a mapping between command line arguments, method arguments, and URLs.
The builder functions add methods to the client object that translate into basic REST functions. All of the 'built' methods return undef on failure of the REST/HTTP call, and auto-decode the returned body into a data structure if it is application/json.
ATTRIBUTES
This class inherits from Mojo::Base, and handles attributes like that class. The following additional attributes are used.
config
Configuration object. Defaults to the appropriate Clustericious::Config class.
ua
User agent to process the HTTP stuff with. Defaults to a Mojo::UserAgent.
client
Deprecated alias for "ua" above. Do not use in new code. May be removed in the future.
app
For testing, you can specify a Mojolicious app name.
server_url
You can override the URL prefix for the client, otherwise it will look it up in the config file.
res, tx
After an HTTP error, the built methods return undef. This function will return the Mojo::Message::Response from the server.
res->code and res->message are the returned HTTP code and message.
tx has the Mojo::Transaction::HTTP object.
METHODS
new
my $f = Foo::Client->new();
my $f = Foo::Client->new(server_url => 'http://someurl');
my $f = Foo::Client->new(app => 'MyApp'); # For testing...
If the configuration file has a "url" entry, this will be used as the default url (first case above).
userinfo
Credentials currently stored.
remote
Tell the client to use the remote information in the configuration. For instance, if the config has
remotes :
test :
url: http://foo
bar :
url: http://baz
username : one
password : two
Then setting remote("test") uses the first url, and setting remote("bar") uses the second one.
remotes
Return a list of available remotes.
login
Log in to the server. This will send basic auth info along with every subsequent request.
$f->login; # looks for username and password in $app.conf
$f->login("elmer", "fudd");
$f->login(username => "elmer", password => "fudd");
errorstring
After an error, this returns an error string made up of the server error code and message. (use res->code and res->message to get the parts)
(e.g. "Error: (500) Internal Server Error")
has_error
Returns true if there was a recent error.
user_agent_string
Returns the user agent string for use in HTTP transactions. By default this includes the clustericious and service version numbers, but you can override it to be whatever you want.
FUNCTIONS
route
route 'subname'; # GET /subname
route subname => '/url'; # GET /url
route subname => GET => '/url'; # GET /url
route subname => POST => '/url'; # POST /url
route subname => DELETE => '/url'; # DELETE /url
route subname => ['SomeObjectClass'];
route subname \"<documentation> <for> <some> <args>";
route_args subname => [ { name => 'param', type => "=s", modifies_url => 'query' } ]
route_args subname => [ { name => 'param', type => "=i", modifies_url => 'append' } ]
Makes a method subname() that does the REST action.
route subname => $url => $doc
is equivalent to
route subname => $url
route_args subname => [ { name => 'all', positional => 'many', modifies_url => 'append' } ];
route_doc subname => $$doc
with the additional differences that GET becomes a POST if the argument is a hashref, and heuristics are used to read YAML files and STDIN.
See route_args and route_doc below.
route_meta
Set metadata attributes for this route.
route_meta 'bucket_map' => { auto_failover => 1 }
route_meta 'bucket_map' => { quiet_post => 1 }
route_meta 'bucket_map' => { skip_existing => 1 }
route_args
Set arguments for this route. This allows command line options to be transformed into method arguments, and allows normalization and validation of method arguments. route_args associates an array ref with the name of a route. Each entry in the array ref is a hashref which may have keys as shown in this example :
route_args send => [
{
name => 'what', # name of the route
type => '=s', # type (see L<Getopt::Long>)
alt => 'long|extra|big', # alternative names
required => 0, # Is it required?
doc => 'get a full status', # brief documentation
},
{
name => 'items', # name of the route
type => '=s', # type (see L<Getopt::Long>)
doc => 'send a list of items' # brief docs
preprocess => 'list' # make an array ref from a list
},
];
The keys have the following effect :
- name
-
The name of the option. This should be preceded by two dashes on the command line. It is also sent as the named argument to the method call.
- type
-
A type, as described in Getopt::Long. This will be appended to the name to form the option specification.
- alt
-
An alternative name or names (joined by |).
- required
-
If this arg is required, set this to 1.
- doc
-
A brief description to be printed in error messages and help documentation.
- preprocess
-
Can be either
yamldoc
,list
ordatetime
.For yamldoc and list, the argument is expected to refer to either a filename which exists, or else "-" for STDIN. The contents are then transformed from YAML (for yamldoc), or split on carriage returns (for list) to form either a data structure or an arrayref, respectively.
For datetime the string is run through Date::Parse and turned into an ISO 8601 datetime.
- modifies_url
-
Describes how the URL is affected by the arguments. Can be 'query', 'append', or a code reference.
'query' adds to the query string, e.g.
route subname '/url' route_args subname => [ { name => 'foo', type => "=s", modifies_url => 'query' } ]
This will cause this invocation :
$foo->subname( "foo" => "bar" )
to send a GET request to /url?foo=bar.
Similarly, 'append' is equivalent to
sub { my ($u,$v) = @_; push @{ $u->path->parts } , $v }
i.e. append the parameter to the end of the URL path.
If route_args is omitted for a route, then arguments with a '--' are treated as part of the query string, and arguments with a '-' are treated as HTTP headers (for a GET request). If a hash reference is passed, the method changes to POST and the hash is encoded into the body as application/json.
- modifies_payload, key
-
Describes how the parameter modifies the payload.
'hash' means set $body->{$name} to $value. 'array' means push ( $name => $value ) onto $body->{$key}. (key should also be specified)
- positional
-
Can be 'one' or 'many'.
If set, this is a positional parameter, not a named parameter. i.e. getopt will not be used to parse the command line, and it will be take from a list sent to the method. For instance
route_args name => [ { name => 'id', positional => 'one' } ];
Then
$client->name($id)
or
commandlineclient name id
will result in the method receiving (id => $id).
If set to 'many', multiple parameters may be sent, e.g.
$client->name($id1, $id2,....)
object
object 'objname'; # defaults to URL /objname
object objname => '/some/url';
Creates two methods, one named with the supplied objname() (used for create, retrieve, update), and one named objname_delete().
Any scalar arguments to the created functions are tacked onto the end of the url. Performs a GET by default, but if you pass a hash reference, the method changes to POST and the hash is encoded into the body as application/json.
The 'object' routes will automatically look for a class named with the object name, but upper case first letter and first after any underscores, which are removed:
object 'myobj'; Foo::Client::Myobj;
object 'my_obj'; Foo::Client::MyObj;
If such a class isn't found, object will default to returning a Clustericious::Client::Object.
meta_for
Get the metadata for a route.
$client->meta_for('welcome');
Returns a Clustericious::Client::Meta::Route object.
COMMON ROUTES
These are routes that are automatically supported by all clients. See Clustericious::Plugin::CommonRoutes.
version
Retrieve the version on the server.
status
Retrieve the status from the server.
api
Retrieve the API from the server
logtail
Get the last N lines of the server log file.
EXAMPLES
package Foo::Client;
use Clustericious::Client;
route 'welcome' => '/'; # GET /
route status; # GET /status
route myobj => [ 'MyObject' ]; # GET /myobj
route something => GET => '/some/';
route remove => DELETE => '/something/';
object 'obj'; # Defaults to /obj
object 'foo' => '/something/foo'; # Can override the URL
route status => \"Get the status"; # Scalar refs are documentation
route_doc status => "Get the status"; # or you can use route_doc
route_args status => [ # route_args sets method or cli arguments
{
name => 'full',
type => '=s',
required => 0,
doc => 'get a full status',
},
];
route_args wrinkle => [ # methods correspond to "route"s
{
name => 'time'
}
];
sub wrinkle { # provides cli command as well as a method
my $c = shift;
my %args = @_;
if ($args{time}) {
...
}
}
----------------------------------------------------------------------
use Foo::Client;
my $f = Foo::Client->new();
my $f = Foo::Client->new(server_url => 'http://someurl');
my $f = Foo::Client->new(app => 'MyApp'); # For testing...
my $welcome = $f->welcome(); # GET /
my $status = $f->status(); # GET /status
my $myobj = $f->myobj('key'); # GET /myobj/key, MyObject->new()
my $something = $f->something('this'); # GET /some/this
$f->remove('foo'); # DELETE /something/foo
my $obj = $f->obj('this', 27); # GET /obj/this/27
# Returns either 'Foo::Client::Obj' or 'Clustericious::Client::Object'
$f->obj({ set => 'this' }); # POST /obj
$f->obj('this', 27, { set => 'this' }); # POST /obj/this/27
$f->obj_delete('this', 27); # DELETE /obj/this/27
my $obj = $f->foo('this'); # GET /something/foo/this
$f->status(full => "yes");
$f->wrinkle( time => 1 );
----------------------
#!/bin/sh
fooclient status
fooclient status --full yes
fooclient wrinkle --time
SEE ALSO
Clustericious::Config, Clustericious, Mojolicious
AUTHOR
Original author: Brian Duggan
Current maintainer: Graham Ollis <plicease@cpan.org>
Contributors:
Curt Tilmes
Yanick Champoux
COPYRIGHT AND LICENSE
This software is copyright (c) 2013 by NASA GSFC.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.