File Coverage

blib/lib/CGI/JSONRPC/Dispatcher.pm
Criterion Covered Total %
statement 28 29 96.5
branch 5 6 83.3
condition n/a
subroutine 7 8 87.5
pod 0 2 0.0
total 40 45 88.8


line stmt bran cond sub pod time code
1             #!perl
2              
3             package CGI::JSONRPC::Dispatcher;
4              
5 1     1   4 use strict;
  1         2  
  1         26  
6 1     1   4 use warnings;
  1         2  
  1         27  
7             our $AUTOLOAD;
8 1     1   12099 use Attribute::Handlers;
  1         6163  
  1         6  
9 1     1   37 use attributes;
  1         2  
  1         5  
10              
11             our %Protected;
12              
13             return 1;
14              
15             sub UNIVERSAL::DontDispatch :ATTR(CODE) {
16 1     1 0 1591 my($package, $symbol) = @_;
17 1         4 $CGI::JSONRPC::Dispatcher::Protected{$package}{*{$symbol}{NAME}}++;
  1         3  
18 1         2 return 1;
19 1     1   120 }
  1         3  
  1         4  
20              
21             sub DISPATCH_OBJECT {
22 0     0 0 0 my($class, $to) = @_;
23              
24             }
25              
26             sub AUTOLOAD {
27 3     3   9 my($class, $id, $to) = splice(@_, 0, 3);
28 3         27 (my $method_name = $AUTOLOAD) =~ s{^.*::}{};
29 3 50       9 die "Can't call a $method_name without a class\n" unless $to;
30 3         17 $to =~ s{[\./]}{::}g;
31 3 100       22 die "$to\::$method_name may not be dispatched\n" if $Protected{$to}{$method_name};
32 2         24 my $object = $to->jsonrpc_new($id, $class);
33 2 100       25 if(my $method = $object->can($method_name)) {
34 1         7 return $method->($object, @_);
35             } else {
36 1         15 die qq{Can't locate object method "$method_name" via package "$to"\n};
37             }
38             }
39              
40             =pod
41              
42             =head1 NAME
43              
44             CGI::JSONRPC::Dispatcher - Dispatch JSONRPC requests to objects
45              
46             =head1 SYNOPSIS
47              
48             package Hello;
49              
50             sub jsonrpc_new {
51             my($class, $id) = @_;
52             my $self = bless { id => $id }, $class;
53             }
54              
55             sub hi {
56             return "hey";
57             }
58              
59             =head1 DESCRIPTION
60              
61             Apache2::JSONRPC::Dispatcher receives JSONRPC class method calls and translates
62             them into perl object method calls. Here's how it works:
63              
64             =head1 FUNCTION
65              
66             =over
67              
68             =item AUTOLOAD($jsonrpc_object, $id, $desired_class, @args)
69              
70             When any function is called in Apache2::JSONRPC::Dispatcher, the
71             C sub runs.
72              
73             =over
74              
75             =item *
76              
77             C<$desired_class> has all of it's dots (.) converted to double-colons (::)
78             to translate JavaScript class names into perl.
79              
80             =item *
81              
82             The C method in the resulting class is called with
83             $id passed in as the first argument. An object should be returned from
84             C in your code.
85              
86             =item *
87              
88             The returned object has the desired method invoked, with any remaining
89             arguments to AUTOLOAD passed in.
90              
91             =back
92              
93             If jsonrpc_new does not exist in the requested package, a fatal error
94             will occur. This both provides you with a handy state mechanism, and ensures
95             that packages that aren't supposed to be accessed from the web aren't.
96              
97             L attempts to call dispatchers with this set of arguments,
98             and then takes any return values, serializes them to JSON, and sends a response
99             back to the client.
100              
101             =head1 PROTECTING METHODS
102              
103             If there are any methods in your RPC objects that shouldn't be called from
104             the web, you can prevent the dispatcher from allowing them by adding the
105             "DontDispatch" attribute, like so:
106              
107             package Authenticator;
108              
109             sub get_password : DontDispatch {
110             [... code the web shouldn't be able to run goes here...]
111             }
112              
113             Note that if you subclass your RPC classes (not always the best approach,
114             but it happens sometimes...) you'll have to protect the method in all your
115             subclasses as well (for now):
116              
117             package Authenticator::Child;
118             sub get_password : DontDispatch {
119             my $self = shift;
120             $self->SUPER::get_password(@_);
121             }
122              
123             =head1 AUTHOR
124              
125             Tyler "Crackerjack" MacDonald and
126             David Labatte
127              
128             =head1 LICENSE
129              
130             Copyright 2008 Tyler "Crackerjack" MacDonald
131              
132             This is free software; You may distribute it under the same terms as perl
133             itself.
134              
135             =head1 SEE ALSO
136              
137             The "examples/httpd.conf" file bundled with the distribution shows how to
138             create a new JSONRPC::Dispatcher-compatible class, and also shows a rather
139             hacky method for making an existing class accessable from JSON.
140              
141             L
142              
143             =cut