NAME

RPC::ExtDirect::Client - Ext.Direct client in Perl

SYNOPSIS

use RPC::ExtDirect::Client;

my $client = RPC::ExtDirect::Client->new(host => 'localhost');

my $result = $client->call(
    action   => 'Action',
    method   => 'Method',
    arg      => [ 'foo', 'bar' ],
    cookies  => { foo => 'bar' },
    metadata => { baz => 'qux' },
);

DESCRIPTION

This module implements Ext.Direct client in pure Perl. Its main purpose is to be used for testing server side Ext.Direct classes, complementing RPC::ExtDirect::Server. It can also be used for testing Ext.Direct Actions developed in languages other than Perl, or for something else altogether.

This client is synchronous, i.e. all method calls are blocking. If you need a non-blocking way of calling an Ext.Direct server, take a look at RPC::ExtDirect::Client::Async instead.

Unless configured otherwise, RPC::ExtDirect::Client will use HTTP::Tiny for the transport layer.

If you are not sure what Ext.Direct is, read RPC::ExtDirect::Intro first.

CAVEATS

Blocking requests

Before a client object can be used, it needs an instance of the Ext.Direct API. There are two ways of initializing the API: remotely from a server, and locally by passing an RPC::ExtDirect::API object instance to the client constructor:

my $api = RPC::ExtDirect::API->new_from_hashref(
    api_href => { ... },
);

my $client = RPC::ExtDirect::Client->new(
    host => 'localhost',
    port => 8080,
    api  => $api,
);

When a local API instance is used, the client object will be available immediately. Otherwise, the constructor will block until the API declaration is retrieved and parsed. This may cause a significant delay that depends on the underlying transport's default timeout for HTTP requests (60 sec for HTTP::Tiny). To avoid that, set the timeout explicitly:

my $client = RPC::ExtDirect::Client->new(
    host    => 'localhost',
    timeout => 1, # This parameter is passed to HTTP::Tiny
);

Applying a timeout in the constructor will set it for every request made by the client object; if that is not desirable, you can set a timeout individually for each request:

my $client = RPC::ExtDirect::Client->new(
    host    => 'localhost',
    timeout => 10, # Initialization may be slow
);

my $data = $client->call(
    timeout => 1, # This *should* work fast, or else
    ...
);

For transport modules other than HTTP::Tiny you may have to use a different parameter to set the timeout.

Error handling

RPC::ExtDirect::Client tries to follow the principle of least astonishment, and will throw an exception by calling Carp::croak whenever it encounters an error. This can happen in any method call:

  • In constructor, if the remote API declaration retrieval failed or the result is garbled;

  • In "call"/"submit"/"poll", if HTTP request failed;

  • In "call", if the arguments do not conform to the Method's definition;

  • In "call" or "poll", if the corresponding API type is not defined, etc.

It is strongly recommended to guard calls to the client object in eval blocks if you require any kind of error handling besides basic error message printed to STDERR:

my $client = eval { RPC::ExtDirect::Client->new( ... ) }
    or do { ... # Handle the error };

my $data = eval { $client->call( ... ) };

if ( $@ ) {
    ...
}

CLIENT OBJECT INTERFACE

RPC::ExtDirect::Client provides several public methods:

new

Constructor. Returns a new client instance and initializes an Ext.Direct API instance from the server, unless "api" parameter is provided. Accepts named arguments in a hash.

Parameters:

api

Optional RPC::ExtDirect::API instance to use. If not given, a new instance will be created from the remote API provided by the server.

config

Optional RPC::ExtDirect::Config instance to be used. If not provided, a new Config instance will be created unless "api" parameter is provided, in which case the Config instance in the API object will be used.

host

Server's host name or IP address. This parameter is mandatory.

port

Optional port number to use when connecting to the server. Defaults to 80.

proto

Optional protocol to use when connecting to the server. Defaults to http.

cookies

Cookies to set when calling server side; can be either HTTP::Cookies object or a hashref containing key-value pairs. Setting this in constructor will pass the same cookies to all subsequent client calls.

The following parameters are deprecated and should be set on a Config instance instead:

api_path

URI for Ext.Direct API published by server. See "api_path" in RPC::ExtDirect::Config.

router_path

URI for Ext.Direct remoting requests. See "router_path" in RPC::ExtDirect::Config.

poll_path

URI for Ext.Direct events. See "poll_path" in RPC::ExtDirect::Config.

remoting_var

JavaScript variable name used to assign Ext.Direct remoting API object to. See "remoting_var" in RPC::ExtDirect::Config.

polling_var

JavaScript variable name used to assign Ext.Direct polling API object to. See "polling_var" in RPC::ExtDirect::Config.

All other arguments are passed to the transport module constructor. See "new" in HTTP::Tiny for more detail.

get_api

Instance method. Returns an "api_class_client" object with the Ext.Direct API declaration published by the server.

Accepts one mandatory positional argument, API type, that can be either 'remoting' or 'polling' to retrieve the corresponding API object.

call

Instance method. Calls the specified Ext.Direct Method on the server side and returns the execution Result, or an Exception. Accepts named arguments in a hash.

Parameters:

action

Ext.Direct Action (class) name. This parameter is mandatory.

method

Ext.Direct Method name to call. This parameter is mandatory.

arg

Ext.Direct Method arguments; use arrayref for methods that accept ordered parameters or hashref for named parameters. This parameter is mandatory even for Methods that accept no arguments; in such case, pass an empty arrayref.

metadata

Ext.Direct Method metadata; use arrayref for methods that accept ordered metadata or hashref for named metadata. Metadata is always optional.

cookies

Optional set of cookies for this particular call only. Cookies should be in the same format as for constructor, see "new".

All other arguments are passed to the transport module constructor. See "new" in HTTP::Tiny for more detail.

submit

Instance method. Submits an HTML form request to a Form Handler method and returns the execution Result, or an Exception. Accepts named arguments in a hash.

Parameters:

action

Ext.Direct Action (class) name. This parameter is mandatory.

method

Ext.Direct Method name to call. This parameter is mandatory.

arg

A hashref of the Method arguments. This parameter is mandatory, unless "upload" is specified.

metadata

A hash- or arrayref of Method metadata. This parameter is always optional.

upload

An optional arrayref of file names to upload. Files should be readable by the current process, or "submit" will die with an error.

cookies

Optional set of cookies for this particular call only. Cookies should be in the same format as for constructor, see "new".

All other arguments are passed to the transport module constructor. See "new" in HTTP::Tiny for more detail.

upload

A shortcut for "submit", for better readability when uploading files.

poll

Instance method. Polls server side for Ext.Direct Events, returns a list of hashrefs with event data. If so desired, these hashrefs can be used to instantiate RPC::ExtDirect::Event objects:

my @events = map { RPC::ExtDirect::Event->new($_) } $client->poll();

PLEASE NOTE that in versions < 1.0 this method used to return a scalar value which could be either a single event hashref, or an arrayref of event hashrefs. It will continue following that behavior when called in scalar context, but doing that is no longer recommended (although not exactly deprecated).

This method accepts the following named parameters in a hashref:

cookies

Optional set of cookies for this particular call only. Cookies should be in the same format as for constructor, see "new".

All other arguments are passed to the transport module constructor. See "new" in HTTP::Tiny for more detail.

CONFIGURATION OPTIONS

RPC::ExtDirect::Client adds the following options specific to the Client, and sets them in the RPC::ExtDirect::Config instance it uses:

api_class_client

Class name to use when instantiating API objects from remote server JavaScript response. Default is RPC::ExtDirect::Client::API; use subclass name if you need to augment the stock API class behavior.

transport_class

Class name to use when instantiating transport objects that are used to connect to the remote server. Default is HTTP::Tiny.

ACCESSOR METHODS

For RPC::ExtDirect::Client, the following accessor methods are provided:

config

Return the current RPC::ExtDirect::Config instance held in the client object, or set a new one.

host

Return the current host name or IP address of the server, or set a new one.

port

Return the current port to use when connecting to the server, or set a new one.

cookies

Return the set of cookies to use with every Ext.Direct request, or set a new one. See "new" for more information.

http_params

Return a hashref with HTTP parameters to be used with every Ext.Direct request, or set a new one. These parameters will be passed to the transport object's constructor (see "transport_class").

By default this hashref will be populated with all "extra" arguments passed to "new" and does not need to be manipulated directly.

SEE ALSO

For more information on using Ext.Direct with Perl, see RPC::ExtDirect. RPC::ExtDirect::Server can be used to provide lightweight drop-in for production environment to run Ext.Direct tests. Tests themselves are better written using Test::ExtDirect that will utilize both ::Server and ::Client in transparent and convenient fashion.

ACKNOWLEDGEMENTS

I would like to thank IntelliSurvey, Inc for sponsoring my work on this module.

BUGS AND LIMITATIONS

At this time there are no known bugs in this module. Please report problems to the author, patches are always welcome.

Use Github tracker to open bug reports, this is the easiest and quickest way to get your issue fixed.

COPYRIGHT AND LICENSE

Copyright (c) 2012-2016 Alex Tokarev <tokarev@cpan.org>.

This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See perlartistic.