NAME
RPC::ExtDirect - Easily integrate Perl server code with JavaScript apps
SYNOPSIS
package Foo::Bar;
use RPC::ExtDirect Action => 'FooBar';
sub sum : ExtDirect( len => 2 ) {
my ($class, $a, $b) = @_;
return $a + $b;
}
sub login : ExtDirect( params => [qw/ user pass /] ) {
my ($class, %arg) = @_;
if ( $arg{user} eq 'foo' && $arg{pass} eq 'bar' ) {
return {
success => \1, # JSON::true
};
}
else {
return {
success => \0, # JSON::false
error => "You shall not pass!"
};
}
}
DESCRIPTION
RPC::ExtDirect suite of modules provides an easy, simple and robust way to write Perl server side code that could be used with HTML5 Rich Internet Applications based on JavaScript frameworks Ext JS and Sencha Touch.
The suite consists of the core RPC::ExtDirect module that implements Ext.Direct protocol and transport layer, several server environment-specific peripheral gateways, a standalone pure Perl server, two Perl clients, and even its own specialized testing scaffold! We've got it covered front to back. :)
INTRODUCTION AND EXAMPLES
If you are not familiar with Ext.Direct, start with RPC::ExtDirect::Intro for more explanations and a few examples, both easy and more advanced.
WHEN TO USE IT, AND WHY
Ext.Direct is a Remote Procedure Call (RPC) protocol provided out of the box with JavaScript frameworks by Sencha. It is deeply integrated in the data services, and is supported by a slew of components. Besides that, Ext.Direct also has several major advantages over similar protocols like XML-RPC and JSON-RPC:
Built in service discovery mechanism: server side API is published to the client via GET requests to a preconfigured URI
Dead simple client side invocation via functional stubs created from the API declaration
Support for request batching with configurable timeout
Easy file uploads via form submits, with all the complexity handled behind the curtains by the framework and the server side stack
Asynchronous push notifications via event polling
All this makes Ext.Direct a no-brainer when developing Web apps with Ext JS or Sencha Touch. And with RPC::ExtDirect, choosing Perl to write server side code for Web apps comes naturally, too. :)
HOW TO USE
Since Ext.Direct is just a transport layer, you don't need to change your app architecture to work around it. If you have an existing server side API you can publish it with minimal effort; if you're starting from scratch, add the classes and methods as you go.
Note that with Ext.Direct, we're talking about classes and methods - that owes to the fact that Ext.Direct originated in Ext JS framework, which itself is written in JavaScript with object-oriented approach in mind. This does not mean you can't go functional or even procedural with RPC::ExtDirect; it is perfectly possible to cook your own flavor of spaghetti code under the light OOP sauce that RPC::ExtDirect provides.
In order for a method to be published to the outside world, it needs to be declared in the Ext.Direct API. As of version 3.0, it can be done in two ways: either with ExtDirect
attribute as shown in the "SYNOPSIS", or by including the method in a hashref fed to RPC::ExtDirect::API constructor. See "COMPILE VS RUN TIME DEFINITION" in RPC::ExtDirect::API for more detail.
METHODS AND CALLING CONVENTIONS
Unlike Ext.Direct specification (and reference PHP implementation, too) RPC::ExtDirect does not impose strict architectural notation on server side code. There is no mandatory object instantiation and no assumption about the code called. That said, an RPC::ExtDirect Method should conform to the following conventions:
Be a class method, i.e. be aware that its first argument will be the package (class) name. Just ignore it if you don't want it.
Ordered (numbered) arguments are passed as list in
@_
, so$_[1]
is the first argument. No more than number of arguments declared in the Method definition will be passed to the Method; any extra will be dropped silently. Less arguments than declared will result in an Exception returned to the client side, and Method never gets called.Named arguments are passed as a hash in
@_
. No arguments other than declared will be passed to the Method; extra arguments will be dropped silently. If not all arguments are present for the remoting invocation, an Exception will be returned and the Method never gets called.Starting with Ext JS 4.2.2, it is possble to relax the argument checking requirements; see "Lazy parameter checking" in RPC::ExtDirect::API for more information.
Form handlers are passed their arguments as a hash in
@_
. Standard Ext.Direct form field values are removed from the argument hash; uploaded file(s) will be passed in thefile_uploads
hash element. It will only be present when there are uploaded files. For more info, see "FILE UPLOADS".Note that any field values in a submitted form will be JSON encoded by the client side.
All remoting Methods are called in scalar context. Returning one scalar value is OK; returning array- or hashref is OK too.
Do not return blessed objects; it is almost always not obvious how to serialize them into JSON that is expected by the client side. JSON encoder will choke and an Exception will be returned to the client. Having said that, if you know what you are doing, it is possible to adjust the Serializer's behavior with "json_options" in RPC::ExtDirect::Config Config option.
If an error is encountered while processing request, throw an exception:
die "My error string\n"
. Note that"\n"
at the end of error string; if you don't add it,die()
will append file name and line number to the error message which is probably not the best idea for errors that are not shown in server console but rather passed on to the JavaScript client.RPC::ExtDirect will trim that last
"\n"
for you before sending the Exception back to the client side.Poll handler methods are called in list context and do not receive any arguments except an environment object. Return value must be a list of instantiated Event objects, see RPC::ExtDirect::Event for more detail.
HOOKS
Hooks provide an option to intercept method calls and modify arguments passed to the methods, or cancel their execution. Hooks are intended to be used as a shim between task-oriented Methods and Web specifics.
Methods should not, to the reasonable extent, be aware of their environment or care about it; Hooks are expected to know how to deal with Web intricacies but not be task oriented.
The best uses for Hooks are: application or package-wide pre-call setup, user authorization, logging, cleanup, testing, etc. Or you can think of the Hooks as poor man's method wrappers without Moose's power (and associated costs).
See more in RPC::ExtDirect::API::Hook.
ENVIRONMENT OBJECTS
Since Hooks, and sometimes Methods too, need to be aware of their Web environment, it is necessary to give them access to it in some way without locking in on platform specifics. RPC::ExtDirect's answer to this problem is environment objects.
An environment object provides platform-agnostic interface for accessing HTTP headers, cookies, form field values, etc. Such object is guaranteed to have the same set of methods that behave the same way across all platforms supported by RPC::ExtDirect, avoiding portability issues.
The interface is modeled after the de facto standard CGI.pm:
$value = $env->param('name')
will retrieve a parameter by name@list = $env->param()
will get the list of available parameters$cookie = $env->cookie('name')
will retrieve a cookie@cookies = $env->cookie()
will return the list of cookies$header = $env->http('name')
will return an HTTP header@headers = $env->http()
will return the list of HTTP headers
Of course it is possible to use environment object in a more sophisticated way if you like to, however do not rely on it having a well-known class name as it is not guaranteed. Environment objects are simple helpers held together by duck type.
Starting with RPC::ExtDirect 3.0, only Hooks will receive an environment object by default. For Methods to receive them as well, you need to specify a "env_arg" in RPC::ExtDirect::API::Method parameter in Method definition.
FILE UPLOADS
Ext.Direct offers native support for file uploading by using temporary HTML forms. RPC::ExtDirect supports this feature; upload requests can be processed in a Form Handler Method. The interface aims to be platform agnostic and will try to do its best to provide the same results in all HTTP environments supported by RPC::ExtDirect.
In a Form Handler Method, arguments are passed as a hash. If one or more file uploads were associated with request, the argument hash will contain a key with value set to arrayref of file hashrefs. The default name for this key is file_uploads
; this can be configured using upload_arg Method parameter.
Each file hashref will have the following keys:
type
-
MIME type of the file, if provided
size
-
File size, in octets
path
-
Path to a temporary file that holds uploaded content
handle
-
Open IO::Handle for the temporary file
basename
-
Name portion of the originally submitted file name, if provided by the client side
filename
-
Full original path as sent by the client, if any
All files passed to a Method need to be processed in that Method; existence of temporary files is not guaranteed after Method returns.
GATEWAYS
In RPC::ExtDirect parlance, a Gateway is a module that deals with the specifics of a particular Web server environment. At the time of writing this documentation, the following gateways are available for RPC::ExtDirect:
- CGI gateway
-
CGI::ExtDirect is used with the ole goode CGI environment; it is also compatible with the newer CGI::Simple module that is a drop-in replacement for
CGI.pm
.This gateway is most often used for testing Ext.Direct interfaces, usually with Test::ExtDirect helper module. However, CGI environment is easy to use and set up practically anywhere, and it can be used in the variety of situations where a full blown Perl application server is not feasible.
One example of such usage would be retrofitting a legacy system with a modern HTML5 Web interface.
- Plack gateway
-
Plack::Middleware::ExtDirect implements an RPC::ExtDirect interface for Plack application server environment. This gateway should also be used instead of the Apache gateway in mod_perl environment.
- AnyEvent::HTTPD gateway
-
AnyEvent::HTTPD::ExtDirect implements a completely asynchronous interface for RPC::ExtDirect, based on AnyEvent::HTTPD module.
- Apache gateway
-
Apache::ExtDirect is a legacy gateway for Apache/mod_perl environment. Since it was written, Apache has fallen out of usage with the author and so the gateway is mostly unsupported. You can use Plack gateway instead, with one of the built in Apache/Plack handlers.
MIGRATING FROM PREVIOUS VERSIONS
If you are using less than current RPC::ExtDirect version, please refer to RPC::ExtDirect::Migration document for the notes and explanations that might prove useful for migration.
DEPENDENCIES
RPC::ExtDirect is dependent on the following modules: Attribute::Handlers, JSON.
BUGS AND LIMITATIONS
There are no known bugs in this module. Please report problems to the author, patches are welcome.
Use Github tracker to open bug reports, this is the easiest and quickest way to get your issue fixed.
SEE ALSO
Take a look at these useful modules that are a part of RPC::ExtDirect family:
RPC::ExtDirect::Server - a prebuilt Ext.Direct server in Perl, based on HTTP::Server::Simple.
RPC::ExtDirect::Client - a synchronous Ext.Direct client in Perl.
RPC::ExtDirect::Client::Async - a fully asynchronous Ext.Direct client in Perl, with API compatible to RPC::ExtDirect::Client.
Test::ExtDirect - a set of helper subroutines that make unit testing Ext.Direct APIs a breeze.
Also you can find additional information in the following Web site links:
AUTHOR
Alex Tokarev <tokarev@cpan.org>
ACKNOWLEDGEMENTS
I would like to thank IntelliSurvey, Inc for sponsoring my work on versions 2.x and 3.x of the RPC::ExtDirect suite of modules.
LICENSE AND COPYRIGHT
Copyright (c) 2011-2014 by Alex Tokarev.
This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See "perlartistic".