File Coverage

blib/lib/Dancer/Plugin/RPC/XML.pm
Criterion Covered Total %
statement 7 9 77.7
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 10 12 83.3


line stmt bran cond sub pod time code
1             package Dancer::Plugin::RPC::XML;
2              
3 2     2   37811 use strict;
  2         4  
  2         74  
4 2     2   10 use warnings;
  2         4  
  2         59  
5              
6 2     2   939 use Dancer ':syntax';
  0            
  0            
7             use Dancer::Exception ':all';
8             use Dancer::Plugin;
9             use RPC::XML;
10             use RPC::XML::ParserFactory;
11              
12             our $VERSION = '0.06';
13              
14             register 'xmlrpc' => \&xmlrpc;
15             register 'xmlrpc_fault' => \&xmlrpc_fault;
16              
17             hook before => sub {
18             if (request->is_post) {
19             content_type('text/xml');
20             }
21             };
22              
23             sub xmlrpc {
24             my ($pattern, @rest) = @_;
25            
26             my $code;
27             for my $e (@rest) {
28             $code = $e if ref($e) eq 'CODE';
29             }
30              
31             my $rpcxml_route = sub {
32             if ( not request->is_post ) {
33             pass and return 0;
34             }
35            
36             # disable layout
37             my $layout = setting('layout');
38             setting('layout' => undef);
39            
40             # parse the request body
41             my $xml = request->body;
42            
43             return RPC::XML::response->new(
44             RPC::XML::fault->new(-1, "XML parse failure - empty"))->as_string if ( !$xml || $xml =~ /^\s?$/ );
45            
46             my $reqobj = RPC::XML::ParserFactory->new()->parse( $xml );
47            
48             if ( not ref $reqobj ) {
49             return RPC::XML::response->new(
50             RPC::XML::fault->new(-2, "XML parse failure: $reqobj"))->as_string;
51             }
52            
53             my @data = @{$reqobj->args};
54             my $name = $reqobj->name;
55            
56             my @values = ();
57             for my $v (@data) { push @values, $v->value; };
58            
59             # stuff data into params
60             request->_set_route_params( { 'method' => $name, 'data' => \@values } );
61            
62             # call the code
63             my $response = try {
64             $code->();
65             } catch {
66             my $e = $_;
67             setting('layout' => $layout);
68             die $e;
69             };
70              
71             # re-enable layout
72             setting('layout' => $layout);
73              
74             # wrap the response in xml with RPC::XML
75             if ( ref $response ne 'RPC::XML::response' ) {
76             return RPC::XML::response->new( $response )->as_string;
77             }
78             else {
79             return $response->as_string;
80             }
81             };
82              
83             # rebuild the @rest array with the compiled route handler
84             my @compiled_rest;
85             for my $e (@rest) {
86             if (ref($e) eq 'CODE') {
87             push @compiled_rest, {}, $rpcxml_route;
88             }
89             else {
90             push @compiled_rest, {}, $e;
91             }
92             }
93            
94             any ['post'] => $pattern, @compiled_rest;
95             #any ['get', 'post'] => $pattern, @compiled_rest;
96             }
97              
98             sub xmlrpc_fault {
99             return RPC::XML::response->new(RPC::XML::fault->new( @_ ));
100             };
101              
102             register_plugin;
103             1; # End of Dancer::Plugin::RPC::XML
104              
105             =head1 NAME
106              
107             Dancer::Plugin::RPC::XML - A plugin for Dancer to wrap XML-RPC calls
108              
109             =head1 VERSION
110              
111             Version 0.06
112              
113             =head1 SYNOPSIS
114              
115             Quick summary of what the module does.
116              
117             # in your app.pl
118             use Dancer::Plugin::RPC::XML;
119              
120             xmlrpc '/foo/bar' => sub {
121             # methodname
122             my $method = params->{method};
123             # listref of data
124             my $data = params->{data};
125              
126             return xmlrpc_fault(100,"Undefined method") unless $method =~ /something_known/;
127              
128             my $response;
129            
130             $response->{name} = "John Smith";
131              
132             return $response;
133             };
134            
135             =head1 REGISTERED METHODS
136              
137             =head2 xmlrpc
138            
139             Route handler for xmlrpc routes. Unwraps requests and re-wraps responses in xml using
140             the RPC::XML module.
141              
142             =head2 xmlrpc_fault( $faultCode, $faultString )
143              
144             Returns xmlrpc fault xml
145              
146             =head1 AUTHOR
147              
148             Jesper Dalberg, C<< >>
149              
150             =head1 BUGS
151              
152             Please report any bugs or feature requests to C, or through
153             the web interface at L. I will be notified, and then you'll
154             automatically be notified of progress on your bug as I make changes.
155              
156             =head1 SUPPORT
157              
158             You can find documentation for this module with the perldoc command.
159              
160             perldoc Dancer::Plugin::RPC::XML
161              
162             You can also look for information at:
163              
164             =over 4
165              
166             =item * RT: CPAN's request tracker
167              
168             L
169              
170             =item * AnnoCPAN: Annotated CPAN documentation
171              
172             L
173              
174             =item * CPAN Ratings
175              
176             L
177              
178             =item * Search CPAN
179              
180             L
181              
182             =back
183              
184             =head1 ACKNOWLEDGEMENTS
185              
186             =over
187              
188             =item * Thanks to Randy J Ray (RJRAY) for the wonderful RPC::XML module
189            
190             =item * Thanks to the Dancer project for creating an alternative to CGI!
191              
192             =back
193              
194             =head1 COPYRIGHT & LICENSE
195              
196             Copyright 2012 Jesper Dalberg, all rights reserved.
197              
198             This program is free software; you can redistribute it and/or modify it
199             under the same terms as Perl itself.
200              
201             =cut