forked from redhotpenguin/perl-soaplite
-
Notifications
You must be signed in to change notification settings - Fork 0
/
README
1683 lines (1275 loc) · 61.1 KB
/
README
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
NAME
SOAP::Lite - Perl's Web Services Toolkit
DESCRIPTION
SOAP::Lite is a collection of Perl modules which provides a simple and
lightweight interface to the Simple Object Access Protocol (SOAP) both
on client and server side.
PERL VERSION WARNING
As of version SOAP::Lite version 1.0, no perl versions before 5.8 will
be supported.
SOAP::Lite 0.71 will be the last version of SOAP::Lite running on perl
5.005
Future versions of SOAP::Lite will require at least perl 5.6.0
If you have not had the time to upgrade your perl, you should consider
this now.
OVERVIEW OF CLASSES AND PACKAGES
lib/SOAP/Lite.pm
SOAP::Lite - Main class provides all logic
SOAP::Transport - Transport backend
SOAP::Data - Data objects
SOAP::Header - Header Data Objects
SOAP::Serializer - Serializes data structures to SOAP messages
SOAP::Deserializer - Deserializes SOAP messages into SOAP::SOM
objects
SOAP::SOM - SOAP Message objects
SOAP::Constants - Provides access to common constants and defaults
SOAP::Trace - Tracing facilities
SOAP::Schema - Provides access and stub(s) for schema(s)
SOAP::Schema::WSDL - WSDL implementation for SOAP::Schema
SOAP::Server - Handles requests on server side
SOAP::Server::Object - Handles objects-by-reference
SOAP::Fault - Provides support for Faults on server side
SOAP::Utils - A set of private and public utility subroutines
lib/SOAP/Packager.pm
SOAP::Packager - Provides an abstract class for implementing custom
packagers.
SOAP::Packager::MIME - Provides MIME support to SOAP::Lite
SOAP::Packager::DIME - Provides DIME support to SOAP::Lite
lib/SOAP/Transport/HTTP.pm
SOAP::Transport::HTTP::Client - Client interface to HTTP transport
SOAP::Transport::HTTP::Server - Server interface to HTTP transport
SOAP::Transport::HTTP::CGI - CGI implementation of server interface
SOAP::Transport::HTTP::Daemon - Daemon implementation of server
interface
SOAP::Transport::HTTP::Apache - mod_perl implementation of server
interface
lib/SOAP/Transport/POP3.pm
SOAP::Transport::POP3::Server - Server interface to POP3 protocol
lib/SOAP/Transport/MAILTO.pm
SOAP::Transport::MAILTO::Client - Client interface to SMTP/sendmail
lib/SOAP/Transport/LOCAL.pm
SOAP::Transport::LOCAL::Client - Client interface to local transport
lib/SOAP/Transport/TCP.pm
SOAP::Transport::TCP::Server - Server interface to TCP protocol
SOAP::Transport::TCP::Client - Client interface to TCP protocol
lib/SOAP/Transport/IO.pm
SOAP::Transport::IO::Server - Server interface to IO transport
METHODS
All accessor methods return the current value when called with no
arguments, while returning the object reference itself when called with
a new value. This allows the set-attribute calls to be chained together.
new(optional key/value pairs)
$client = SOAP::Lite->new(proxy => $endpoint)
Constructor. Many of the accessor methods defined here may be
initialized at creation by providing their name as a key, followed
by the desired value. The example provides the value for the proxy
element of the client.
transport(optional transport object)
$transp = $client->transport( );
Gets or sets the transport object used for sending/receiving SOAP
messages.
See SOAP::Transport for details.
serializer(optional serializer object)
$serial = $client->serializer( )
Gets or sets the serializer object used for creating XML messages.
See SOAP::Serializer for details.
packager(optional packager object)
$packager = $client->packager( )
Provides access to the "SOAP::Packager" object that the client uses
to manage the use of attachments. The default packager is a MIME
packager, but unless you specify parts to send, no MIME formatting
will be done.
See also: SOAP::Packager.
proxy(endpoint, optional extra arguments)
$client->proxy('http://soap.xml.info/ endPoint');
The proxy is the server or endpoint to which the client is going to
connect. This method allows the setting of the endpoint, along with
any extra information that the transport object may need when
communicating the request.
This method is actually an alias to the proxy method of
SOAP::Transport. It is the same as typing:
$client->transport( )->proxy(...arguments);
Extra parameters can be passed to proxy() - see below.
compress_threshold
See COMPRESSION in HTTP::Transport.
All initialization options from the underlying transport layer
The options for HTTP(S) are the same as for LWP::UserAgent's
new() method.
A common option is to create a instance of HTTP::Cookies and
pass it as cookie_jar option:
my $cookie_jar = HTTP::Cookies->new()
$client->proxy('http://www.example.org/webservice',
cookie_jar => $cookie_jar,
);
For example, if you wish to set the HTTP timeout for a SOAP::Lite
client to 5 seconds, use the following code:
my $soap = SOAP::Lite
->uri($uri)
->proxy($proxyUrl, timeout => 5 );
See LWP::UserAgent.
endpoint(optional new endpoint address)
$client->endpoint('http://soap.xml.info/ newPoint')
It may be preferable to set a new endpoint without the additional
work of examining the new address for protocol information and
checking to ensure the support code is loaded and available. This
method allows the caller to change the endpoint that the client is
currently set to connect to, without reloading the relevant
transport code. Note that the proxy method must have been called
before this method is used.
service(service URL)
$client->service('http://svc.perl.org/Svc.wsdl');
"SOAP::Lite" offers some support for creating method stubs from
service descriptions. At present, only WSDL support is in place.
This method loads the specified WSDL schema and uses it as the basis
for generating stubs.
outputxml(boolean)
$client->outputxml('true');
When set to a true value, the raw XML is returned by the call to a
remote method.
The default is to return the a SOAP::SOM object (false).
autotype(boolean)
$client->autotype(0);
This method is a shortcut for:
$client->serializer->autotype(boolean);
By default, the serializer tries to automatically deduce types for
the data being sent in a message. Setting a false value with this
method disables the behavior.
readable(boolean)
$client->readable(1);
This method is a shortcut for:
$client->serializer->readable(boolean);
When this is used to set a true value for this property, the
generated XML sent to the endpoint has extra characters (spaces and
new lines) added in to make the XML itself more readable to human
eyes (presumably for debugging). The default is to not send any
additional characters.
default_ns($uri)
Sets the default namespace for the request to the specified uri.
This overrides any previous namespace declaration that may have been
set using a previous call to "ns()" or "default_ns()". Setting the
default namespace causes elements to be serialized without a
namespace prefix, like this:
<soap:Envelope>
<soap:Body>
<myMethod xmlns="http://www.someuri.com">
<foo />
</myMethod>
</soap:Body>
</soap:Envelope>
Some .NET web services have been reported to require this XML
namespace idiom.
ns($uri,$prefix=undef)
Sets the namespace uri and optionally the namespace prefix for the
request to the specified values. This overrides any previous
namespace declaration that may have been set using a previous call
to "ns()" or "default_ns()".
If a prefix is not specified, one will be generated for you
automatically. Setting the namespace causes elements to be
serialized with a declared namespace prefix, like this:
<soap:Envelope>
<soap:Body>
<my:myMethod xmlns:my="http://www.someuri.com">
<my:foo />
</my:myMethod>
</soap:Body>
</soap:Envelope>
use_prefix(boolean)
Deprecated. Use the "ns()" and "default_ns" methods described above.
Shortcut for "serializer->use_prefix()". This lets you turn on/off
the use of a namespace prefix for the children of the /Envelope/Body
element. Default is 'true'.
When use_prefix is set to 'true', serialized XML will look like
this:
<SOAP-ENV:Envelope ...attributes skipped>
<SOAP-ENV:Body>
<namesp1:mymethod xmlns:namesp1="urn:MyURI" />
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
When use_prefix is set to 'false', serialized XML will look like
this:
<SOAP-ENV:Envelope ...attributes skipped>
<SOAP-ENV:Body>
<mymethod xmlns="urn:MyURI" />
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Some .NET web services have been reported to require this XML
namespace idiom.
soapversion(optional value)
$client->soapversion('1.2');
If no parameter is given, returns the current version of SOAP that
is being used by the client object to encode requests. If a
parameter is given, the method attempts to set that as the version
of SOAP being used.
The value should be either 1.1 or 1.2.
envprefix(QName)
$client->envprefix('env');
This method is a shortcut for:
$client->serializer->envprefix(QName);
Gets or sets the namespace prefix for the SOAP namespace. The
default is SOAP.
The prefix itself has no meaning, but applications may wish to chose
one explicitly to denote different versions of SOAP or the like.
encprefix(QName)
$client->encprefix('enc');
This method is a shortcut for:
$client->serializer->encprefix(QName);
Gets or sets the namespace prefix for the encoding rules namespace.
The default value is SOAP-ENC.
While it may seem to be an unnecessary operation to set a value that
isn't relevant to the message, such as the namespace labels for the
envelope and encoding URNs, the ability to set these labels explicitly
can prove to be a great aid in distinguishing and debugging messages on
the server side of operations.
encoding(encoding URN)
$client->encoding($soap_12_encoding_URN);
This method is a shortcut for:
$client->serializer->encoding(args);
Where the earlier method dealt with the label used for the
attributes related to the SOAP encoding scheme, this method actually
sets the URN to be specified as the encoding scheme for the message.
The default is to specify the encoding for SOAP 1.1, so this is
handy for applications that need to encode according to SOAP 1.2
rules.
typelookup
$client->typelookup;
This method is a shortcut for:
$client->serializer->typelookup;
Gives the application access to the type-lookup table from the
serializer object. See the section on SOAP::Serializer.
uri(service specifier)
Deprecated - the "uri" subroutine is deprecated in order to provide
a more intuitive naming scheme for subroutines that set namespaces.
In the future, you will be required to use either the "ns()" or
"default_ns()" subroutines instead of "uri()".
$client->uri($service_uri);
This method is a shortcut for:
$client->serializer->uri(service);
The URI associated with this accessor on a client object is the
service-specifier for the request, often encoded for HTTP-based
requests as the SOAPAction header. While the names may seem
confusing, this method doesn't specify the endpoint itself. In most
circumstances, the "uri" refers to the namespace used for the
request.
Often times, the value may look like a valid URL. Despite this, it
doesn't have to point to an existing resource (and often doesn't).
This method sets and retrieves this value from the object. Note that
no transport code is triggered by this because it has no direct
effect on the transport of the object.
multirefinplace(boolean)
$client->multirefinplace(1);
This method is a shortcut for:
$client->serializer->multirefinplace(boolean);
Controls how the serializer handles values that have multiple
references to them. Recall from previous SOAP chapters that a value
may be tagged with an identifier, then referred to in several
places. When this is the case for a value, the serializer defaults
to putting the data element towards the top of the message, right
after the opening tag of the method-specification. It is serialized
as a standalone entity with an ID that is then referenced at the
relevant places later on. If this method is used to set a true
value, the behavior is different. When the multirefinplace attribute
is true, the data is serialized at the first place that references
it, rather than as a separate element higher up in the body. This is
more compact but may be harder to read or trace in a debugging
environment.
parts( ARRAY )
Used to specify an array of MIME::Entity's to be attached to the
transmitted SOAP message. Attachments that are returned in a
response can be accessed by "SOAP::SOM::parts()".
self
$ref = SOAP::Lite->self;
Returns an object reference to the default global object the
"SOAP::Lite" package maintains. This is the object that processes
many of the arguments when provided on the use line.
The following method isn't an accessor style of method but neither does
it fit with the group that immediately follows it:
call(arguments)
$client->call($method => @arguments);
As has been illustrated in previous chapters, the "SOAP::Lite"
client objects can manage remote calls with auto-dispatching using
some of Perl's more elaborate features. call is used when the
application wants a greater degree of control over the details of
the call itself. The method may be built up from a SOAP::Data
object, so as to allow full control over the namespace associated
with the tag, as well as other attributes like encoding. This is
also important for calling methods that contain characters not
allowable in Perl function names, such as A.B.C.
The next four methods used in the "SOAP::Lite" class are geared towards
handling the types of events than can occur during the message
lifecycle. Each of these sets up a callback for the event in question:
on_action(callback)
$client->on_action(sub { qq("$_[0]") });
Triggered when the transport object sets up the SOAPAction header
for an HTTP-based call. The default is to set the header to the
string, uri#method, in which URI is the value set by the uri method
described earlier, and method is the name of the method being
called. When called, the routine referenced (or the closure, if
specified as in the example) is given two arguments, uri and method,
in that order.
.NET web services usually expect "/" as separator for "uri" and
"method". To change SOAP::Lite's behaviour to use uri/method as
SOAPAction header, use the following code:
$client->on_action( sub { join '/', @_ } );
=item on_fault(callback)
$client->on_fault(sub { popup_dialog($_[1]) });
Triggered when a method call results in a fault response from the
server. When it is called, the argument list is first the client
object itself, followed by the object that encapsulates the fault.
In the example, the fault object is passed (without the client
object) to a hypothetical GUI function that presents an error dialog
with the text of fault extracted from the object (which is covered
shortly under the SOAP::SOM methods).
on_nonserialized(callback)
$client->on_nonserialized(sub { die "$_[0]?!?" });
Occasionally, the serializer may be given data it can't turn into
SOAP-savvy XML; for example, if a program bug results in a code
reference or something similar being passed in as a parameter to
method call. When that happens, this callback is activated, with one
argument. That argument is the data item that could not be
understood. It will be the only argument. If the routine returns,
the return value is pasted into the message as the serialization.
Generally, an error is in order, and this callback allows for
control over signaling that error.
on_debug(callback)
$client->on_debug(sub { print @_ });
Deprecated. Use the global +debug and +trace facilities described in
SOAP::Trace
Note that this method will not work as expected: Instead of
affecting the debugging behaviour of the object called on, it will
globally affect the debugging behaviour for all objects of that
class.
WRITING A SOAP CLIENT
This chapter guides you to writing a SOAP client by example.
The SOAP service to be accessed is a simple variation of the well-known
hello world program. It accepts two parameters, a name and a given name,
and returns "Hello $given_name $name".
We will use "Martin Kutter" as the name for the call, so all variants
will print the following message on success:
Hello Martin Kutter!
SOAP message styles
There are three common (and one less common) variants of SOAP messages.
These address the message style (positional parameters vs. specified
message documents) and encoding (as-is vs. typed).
The different message styles are:
* rpc/encoded
Typed, positional parameters. Widely used in scripting languages.
The type of the arguments is included in the message. Arrays and the
like may be encoded using SOAP encoding rules (or others).
* rpc/literal
As-is, positional parameters. The type of arguments is defined by
some pre-exchanged interface definition.
* document/encoded
Specified message with typed elements. Rarely used.
* document/literal
Specified message with as-is elements. The message specification and
element types are defined by some pre-exchanged interface
definition.
As of 2008, document/literal has become the predominant SOAP message
variant. rpc/literal and rpc/encoded are still in use, mainly with
scripting languages, while document/encoded is hardly used at all.
You will see clients for the rpc/encoded and document/literal SOAP
variants in this section.
Example implementations
RPC/ENCODED
Rpc/encoded is most popular with scripting languages like perl, php and
python without the use of a WSDL. Usual method descriptions look like
this:
Method: sayHello(string, string)
Parameters:
name: string
givenName: string
Such a description usually means that you can call a method named
"sayHello" with two positional parameters, "name" and "givenName", which
both are strings.
The message corresponding to this description looks somewhat like this:
<sayHello xmlns="urn:HelloWorld">
<s-gensym01 xsi:type="xsd:string">Kutter</s-gensym01>
<s-gensym02 xsi:type="xsd:string">Martin</s-gensym02>
</sayHello>
Any XML tag names may be used instead of the "s-gensym01" stuff -
parameters are positional, the tag names have no meaning.
A client producing such a call is implemented like this:
use SOAP::Lite;
my $soap = SOAP::Lite->new( proxy => 'http://localhost:81/soap-wsdl-test/helloworld.pl');
$soap->default_ns('urn:HelloWorld');
my $som = $soap->call('sayHello', 'Kutter', 'Martin');
die $som->faultstring if ($som->fault);
print $som->result, "\n";
You can of course use a one-liner, too...
Sometimes, rpc/encoded interfaces are described with WSDL definitions. A
WSDL accepting "named" parameters with rpc/encoded looks like this:
<definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:s="http://www.w3.org/2001/XMLSchema"
xmlns:s0="urn:HelloWorld"
targetNamespace="urn:HelloWorld"
xmlns="http://schemas.xmlsoap.org/wsdl/">
<types>
<s:schema targetNamespace="urn:HelloWorld">
</s:schema>
</types>
<message name="sayHello">
<part name="name" type="s:string" />
<part name="givenName" type="s:string" />
</message>
<message name="sayHelloResponse">
<part name="sayHelloResult" type="s:string" />
</message>
<portType name="Service1Soap">
<operation name="sayHello">
<input message="s0:sayHello" />
<output message="s0:sayHelloResponse" />
</operation>
</portType>
<binding name="Service1Soap" type="s0:Service1Soap">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http"
style="rpc" />
<operation name="sayHello">
<soap:operation soapAction="urn:HelloWorld#sayHello"/>
<input>
<soap:body use="encoded"
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</input>
<output>
<soap:body use="encoded"
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</output>
</operation>
</binding>
<service name="HelloWorld">
<port name="HelloWorldSoap" binding="s0:Service1Soap">
<soap:address location="http://localhost:81/soap-wsdl-test/helloworld.pl" />
</port>
</service>
</definitions>
The message corresponding to this schema looks like this:
<sayHello xmlns="urn:HelloWorld">
<name xsi:type="xsd:string">Kutter</name>
<givenName xsi:type="xsd:string">Martin</givenName>
</sayHello>
A web service client using this schema looks like this:
use SOAP::Lite;
my $soap = SOAP::Lite->service("file:say_hello_rpcenc.wsdl");
eval { my $result = $soap->sayHello('Kutter', 'Martin'); };
if ($@) {
die $@;
}
print $som->result();
You may of course also use the following one-liner:
perl -MSOAP::Lite -e 'print SOAP::Lite->service("file:say_hello_rpcenc.wsdl")\
->sayHello('Kutter', 'Martin'), "\n";'
A web service client (without a service description) looks like this.
use SOAP::Lite;
my $soap = SOAP::Lite->new( proxy => 'http://localhost:81/soap-wsdl-test/helloworld.pl');
$soap->default_ns('urn:HelloWorld');
my $som = $soap->call('sayHello',
SOAP::Data->name('name')->value('Kutter'),
SOAP::Data->name('givenName')->value('Martin')
);
die $som->faultstring if ($som->fault);
print $som->result, "\n";
RPC/LITERAL
SOAP web services using the document/literal message encoding are
usually described by some Web Service Definition. Our web service has
the following WSDL description:
<definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:s="http://www.w3.org/2001/XMLSchema"
xmlns:s0="urn:HelloWorld"
targetNamespace="urn:HelloWorld"
xmlns="http://schemas.xmlsoap.org/wsdl/">
<types>
<s:schema targetNamespace="urn:HelloWorld">
<s:complexType name="sayHello">
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" name="name"
type="s:string" />
<s:element minOccurs="0" maxOccurs="1" name="givenName"
type="s:string" nillable="1" />
</s:sequence>
</s:complexType>
<s:complexType name="sayHelloResponse">
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" name="sayHelloResult"
type="s:string" />
</s:sequence>
</s:complexType>
</s:schema>
</types>
<message name="sayHello">
<part name="parameters" type="s0:sayHello" />
</message>
<message name="sayHelloResponse">
<part name="parameters" type="s0:sayHelloResponse" />
</message>
<portType name="Service1Soap">
<operation name="sayHello">
<input message="s0:sayHello" />
<output message="s0:sayHelloResponse" />
</operation>
</portType>
<binding name="Service1Soap" type="s0:Service1Soap">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http"
style="rpc" />
<operation name="sayHello">
<soap:operation soapAction="urn:HelloWorld#sayHello"/>
<input>
<soap:body use="literal" namespace="urn:HelloWorld"/>
</input>
<output>
<soap:body use="literal" namespace="urn:HelloWorld"/>
</output>
</operation>
</binding>
<service name="HelloWorld">
<port name="HelloWorldSoap" binding="s0:Service1Soap">
<soap:address location="http://localhost:80//helloworld.pl" />
</port>
</service>
</definitions>
The XML message (inside the SOAP Envelope) look like this:
<ns0:sayHello xmlns:ns0="urn:HelloWorld">
<parameters>
<name>Kutter</name>
<givenName>Martin</givenName>
</parameters>
</ns0:sayHello>
<sayHelloResponse xmlns:ns0="urn:HelloWorld">
<parameters>
<sayHelloResult>Hello Martin Kutter!</sayHelloResult>
</parameters>
</sayHelloResponse>
This is the SOAP::Lite implementation for the web service client:
use SOAP::Lite +trace;
my $soap = SOAP::Lite->new( proxy => 'http://localhost:80/helloworld.pl');
$soap->on_action( sub { "urn:HelloWorld#sayHello" });
$soap->autotype(0)->readable(1);
$soap->default_ns('urn:HelloWorld');
my $som = $soap->call('sayHello', SOAP::Data->name('parameters')->value(
\SOAP::Data->value([
SOAP::Data->name('name')->value( 'Kutter' ),
SOAP::Data->name('givenName')->value('Martin'),
]))
);
die $som->fault->{ faultstring } if ($som->fault);
print $som->result, "\n";
DOCUMENT/LITERAL
SOAP web services using the document/literal message encoding are
usually described by some Web Service Definition. Our web service has
the following WSDL description:
<definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:s="http://www.w3.org/2001/XMLSchema"
xmlns:s0="urn:HelloWorld"
targetNamespace="urn:HelloWorld"
xmlns="http://schemas.xmlsoap.org/wsdl/">
<types>
<s:schema targetNamespace="urn:HelloWorld">
<s:element name="sayHello">
<s:complexType>
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" name="name" type="s:string" />
<s:element minOccurs="0" maxOccurs="1" name="givenName" type="s:string" nillable="1" />
</s:sequence>
</s:complexType>
</s:element>
<s:element name="sayHelloResponse">
<s:complexType>
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" name="sayHelloResult" type="s:string" />
</s:sequence>
</s:complexType>
</s:element>
</types>
<message name="sayHelloSoapIn">
<part name="parameters" element="s0:sayHello" />
</message>
<message name="sayHelloSoapOut">
<part name="parameters" element="s0:sayHelloResponse" />
</message>
<portType name="Service1Soap">
<operation name="sayHello">
<input message="s0:sayHelloSoapIn" />
<output message="s0:sayHelloSoapOut" />
</operation>
</portType>
<binding name="Service1Soap" type="s0:Service1Soap">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http"
style="document" />
<operation name="sayHello">
<soap:operation soapAction="urn:HelloWorld#sayHello"/>
<input>
<soap:body use="literal" />
</input>
<output>
<soap:body use="literal" />
</output>
</operation>
</binding>
<service name="HelloWorld">
<port name="HelloWorldSoap" binding="s0:Service1Soap">
<soap:address location="http://localhost:80//helloworld.pl" />
</port>
</service>
</definitions>
The XML message (inside the SOAP Envelope) look like this:
<sayHello xmlns="urn:HelloWorld">
<name>Kutter</name>
<givenName>Martin</givenName>
</sayHello>
<sayHelloResponse>
<sayHelloResult>Hello Martin Kutter!</sayHelloResult>
</sayHelloResponse>
You can call this web service with the following client code:
use SOAP::Lite;
my $soap = SOAP::Lite->new( proxy => 'http://localhost:80/helloworld.pl');
$soap->on_action( sub { "urn:HelloWorld#sayHello" });
$soap->autotype(0);
$soap->default_ns('urn:HelloWorld');
my $som = $soap->call("sayHello",
SOAP::Data->name('name')->value( 'Kutter' ),
SOAP::Data->name('givenName')->value('Martin'),
);
die $som->fault->{ faultstring } if ($som->fault);
print $som->result, "\n";
Differences between the implementations
You may have noticed that there's little difference between the
rpc/encoded, rpc/literal and the document/literal example's
implementation. In fact, from SOAP::Lite's point of view, the only
differences between rpc/literal and document/literal that parameters are
always named.
In our example, the rpc/encoded variant already used named parameters
(by using two messages), so there's no difference at all.
You may have noticed the somewhat strange idiom for passing a list of
named paraneters in the rpc/literal example:
my $som = $soap->call('sayHello', SOAP::Data->name('parameters')->value(
\SOAP::Data->value([
SOAP::Data->name('name')->value( 'Kutter' ),
SOAP::Data->name('givenName')->value('Martin'),
]))
);
While SOAP::Data provides full control over the XML generated, passing
hash-like structures require additional coding.
WRITING A SOAP SERVER
See SOAP::Server, or SOAP::Transport.
FEATURES
ATTACHMENTS
"SOAP::Lite" features support for the SOAP with Attachments
specification. Currently, SOAP::Lite only supports MIME based
attachments. DIME based attachments are yet to be fully functional.
EXAMPLES
Client sending an attachment
"SOAP::Lite" clients can specify attachments to be sent along with a
request by using the "SOAP::Lite::parts()" method, which takes as an
argument an ARRAY of "MIME::Entity"'s.
use SOAP::Lite;
use MIME::Entity;
my $ent = build MIME::Entity
Type => "image/gif",
Encoding => "base64",
Path => "somefile.gif",
Filename => "saveme.gif",
Disposition => "attachment";
my $som = SOAP::Lite
->uri($SOME_NAMESPACE)
->parts([ $ent ])
->proxy($SOME_HOST)
->some_method(SOAP::Data->name("foo" => "bar"));
Client retrieving an attachment
A client accessing attachments that were returned in a response by using
the "SOAP::SOM::parts()" accessor.
use SOAP::Lite;
use MIME::Entity;
my $soap = SOAP::Lite
->uri($NS)
->proxy($HOST);
my $som = $soap->foo();
foreach my $part (${$som->parts}) {
print $part->stringify;
}
Server receiving an attachment
Servers, like clients, use the SOAP::SOM module to access attachments
transmitted to it.
package Attachment;
use SOAP::Lite;
use MIME::Entity;
use strict;
use vars qw(@ISA);
@ISA = qw(SOAP::Server::Parameters);
sub someMethod {
my $self = shift;
my $envelope = pop;
foreach my $part (@{$envelope->parts}) {
print "AttachmentService: attachment found! (".ref($part).")\n";
}
# do something
}
Server responding with an attachment
Servers wishing to return an attachment to the calling client need only
return "MIME::Entity" objects along with SOAP::Data elements, or any
other data intended for the response.
package Attachment;
use SOAP::Lite;
use MIME::Entity;
use strict;
use vars qw(@ISA);
@ISA = qw(SOAP::Server::Parameters);
sub someMethod {
my $self = shift;
my $envelope = pop;
my $ent = build MIME::Entity
'Id' => "<1234>",
'Type' => "text/xml",
'Path' => "some.xml",
'Filename' => "some.xml",
'Disposition' => "attachment";
return SOAP::Data->name("foo" => "blah blah blah"),$ent;
}
DEFAULT SETTINGS
Though this feature looks similar to autodispatch they have (almost)
nothing in common. This capability allows you specify default settings
so that all objects created after that will be initialized with the
proper default settings.
If you wish to provide common "proxy()" or "uri()" settings for all
"SOAP::Lite" objects in your application you may do:
use SOAP::Lite
proxy => 'http://localhost/cgi-bin/soap.cgi',
uri => 'http://my.own.com/My/Examples';
my $soap1 = new SOAP::Lite; # will get the same proxy()/uri() as above
print $soap1->getStateName(1)->result;
my $soap2 = SOAP::Lite->new; # same thing as above
print $soap2->getStateName(2)->result;
# or you may override any settings you want
my $soap3 = SOAP::Lite->proxy('http://localhost/');
print $soap3->getStateName(1)->result;
Any "SOAP::Lite" properties can be propagated this way. Changes in
object copies will not affect global settings and you may still change
global settings with "SOAP::Lite->self" call which returns reference to
global object. Provided parameter will update this object and you can
even set it to "undef":
SOAP::Lite->self(undef);
The "use SOAP::Lite" syntax also lets you specify default event handlers
for your code. If you have different SOAP objects and want to share the
same "on_action()" (or "on_fault()" for that matter) handler. You can
specify "on_action()" during initialization for every object, but you
may also do:
use SOAP::Lite
on_action => sub {sprintf '%s#%s', @_};
and this handler will be the default handler for all your SOAP objects.
You can override it if you specify a handler for a particular object.
See t/*.t for example of on_fault() handler.
Be warned, that since "use ..." is executed at compile time all "use"
statements will be executed before script execution that can make
unexpected results. Consider code:
use SOAP::Lite proxy => 'http://localhost/';
print SOAP::Lite->getStateName(1)->result;
use SOAP::Lite proxy => 'http://localhost/cgi-bin/soap.cgi';
print SOAP::Lite->getStateName(1)->result;
Both SOAP calls will go to 'http://localhost/cgi-bin/soap.cgi'. If you
want to execute "use" at run-time, put it in "eval":
eval "use SOAP::Lite proxy => 'http://localhost/cgi-bin/soap.cgi'; 1" or die;
Or alternatively,