File Coverage

lib/XML/Compile/SOAP/Server.pm
Criterion Covered Total %
statement 21 77 27.2
branch 0 24 0.0
condition 0 15 0.0
subroutine 7 17 41.1
pod 5 6 83.3
total 33 139 23.7


line stmt bran cond sub pod time code
1             # Copyrights 2007-2019 by [Mark Overmeer ].
2             # For other contributors see ChangeLog.
3             # See the manual pages for details on the licensing terms.
4             # Pod stripped from pm file by OODoc 2.02.
5             # This code is part of distribution XML-Compile-SOAP. Meta-POD processed
6             # with OODoc into POD and HTML manual-pages. See README.md
7             # Copyright Mark Overmeer. Licensed under the same terms as Perl itself.
8              
9             package XML::Compile::SOAP::Server;
10 7     7   1113 use vars '$VERSION';
  7         14  
  7         352  
11             $VERSION = '3.26';
12              
13              
14 7     7   36 use warnings;
  7         13  
  7         182  
15 7     7   34 use strict;
  7         11  
  7         194  
16              
17 7     7   43 use Log::Report 'xml-compile-soap';
  7         14  
  7         44  
18              
19 7     7   1848 use XML::Compile::Util qw/unpack_type/;
  7         13  
  7         383  
20 7     7   45 use XML::Compile::SOAP::Util qw/:soap11/;
  7         147  
  7         827  
21 7         5754 use HTTP::Status qw/RC_OK RC_BAD_REQUEST RC_NOT_ACCEPTABLE
22 7     7   3823 RC_INTERNAL_SERVER_ERROR/;
  7         32668  
23              
24              
25 0     0 1   sub new(@) { panic __PACKAGE__." only secundary in multiple inheritance" }
26              
27             sub init($)
28 0     0 0   { my ($self, $args) = @_;
29 0   0       $self->{role} = $self->roleURI($args->{role} || 'NEXT') || $args->{role};
30 0           $self;
31             }
32              
33             #---------------------------------
34              
35              
36 0     0 1   sub role() {shift->{role}}
37              
38             #---------------------------------
39              
40              
41             sub compileHandler(@)
42 0     0 1   { my ($self, %args) = @_;
43              
44 0           my $decode = $args{decode};
45 0   0       my $encode = $args{encode} || $self->compileMessage('SENDER');
46             my $name = $args{name}
47 0 0         or error __x"each server handler requires a name";
48 0   0 0     my $selector = $args{selector} || sub {0};
  0            
49              
50             # even without callback, we will validate
51 0           my $callback = $args{callback};
52              
53             sub
54 0     0     { my ($name, $xmlin, $info, $session) = @_;
55             # info is used to help determine if the xmlin is of the type for
56             # this call. $session is passed in by the server and is in turn
57             # passed to the handlers
58 0 0         $selector->($xmlin, $info) or return;
59 0           trace __x"procedure {name} selected", name => $name;
60              
61 0           my $data;
62 0 0         if($decode)
63 0           { $data = try { $decode->($xmlin) };
  0            
64 0 0         if($@)
65 0           { $@->wasFatal->throw(reason => 'INFO', is_fatal => 0);
66 0           return ( RC_NOT_ACCEPTABLE, 'input validation failed'
67             , $self->faultValidationFailed($name, $@->wasFatal))
68             }
69             }
70             else
71 0           { $data = $xmlin;
72             }
73              
74 0           my $answer = $callback->($self, $data, $session);
75 0 0         unless(defined $answer)
76 0           { notice __x"procedure {name} did not produce an answer", name=>$name;
77 0           return ( RC_INTERNAL_SERVER_ERROR, 'no answer produced'
78             , $self->faultNoAnswerProduced($name));
79             }
80              
81 0 0         if(ref $answer ne 'HASH')
82 0           { notice __x"procedure {name} did not return a HASH", name => $name;
83 0           return ( RC_INTERNAL_SERVER_ERROR, 'invalid answer produced'
84             , $self->faultNoAnswerProduced($name));
85             }
86              
87 0   0       my $rc = (delete $answer->{_RETURN_CODE}) || RC_OK;
88 0   0       my $rc_txt = delete $answer->{_RETURN_TEXT} || 'Answer included';
89              
90 0           my $xmlout = try { $encode->($answer) };
  0            
91 0 0         $@ or return ($rc, $rc_txt, $xmlout);
92              
93 0           my $fatal = $@->wasFatal;
94 0           $fatal->throw(reason => 'ALERT', is_fatal => 0);
95              
96 0           ( RC_INTERNAL_SERVER_ERROR, 'created response not valid'
97             , $self->faultResponseInvalid($name, $fatal)
98             );
99 0           };
100             }
101              
102              
103             sub compileFilter(@)
104 0     0 1   { my ($self, %args) = @_;
105              
106 0           my $need_node;
107 0 0         if($args{style} eq 'rpc')
108             { # RPC-style wraps the body parameters in the procedure name. That's
109             # a logical construction.
110 0 0         $need_node = $args{body}{procedure} or panic;
111             }
112             else
113             { # Document-style does *not* contain the procedure name anywhere! We
114             # can only base the selection on the type of the elements. Therefore,
115             # procedure selection is often based on HTTP header (which was created
116             # for other purposes.
117 0           my $first = $args{body}{parts}[0];
118 0 0         $need_node = $first ? $first->{element} : undef;
119             }
120              
121             $need_node
122 0 0   0     or return sub { !defined $_[1]->{body}[0] }; # empty body
  0            
123              
124 0           my ($need_ns, $need_local) = unpack_type($need_node);
125              
126             # The returned code-ref is called with (XML, INFO)
127             sub {
128 0     0     my ($xml, $info) = @_;
129 0           (my $body) = $xml->getChildrenByLocalName('Body');
130 0           (my $has) = $body->getElementsByTagNameNS($need_ns, $need_local);
131 0           defined $has;
132 0           };
133             }
134              
135              
136             sub faultWriter()
137 0     0 1   { my $thing = shift;
138 0 0         my $self = ref $thing ? $thing : $thing->new;
139 0   0       $self->{fault_writer} ||= $self->compileMessage('SENDER');
140             }
141              
142             1;