1NAME
2 POE::Component::Server::SOAP - publish POE event handlers via SOAP over
3 HTTP
4
5SYNOPSIS
6 use POE;
7 use POE::Component::Server::SOAP;
8
9 POE::Component::Server::SOAP->new(
10 'ALIAS' => 'MySOAP',
11 'ADDRESS' => 'localhost',
12 'PORT' => 32080,
13 'HOSTNAME' => 'MyHost.com',
14 );
15
16 POE::Session->create(
17 'inline_states' => {
18 '_start' => \&setup_service,
19 '_stop' => \&shutdown_service,
20 'Sum_Things' => \&do_sum,
21 },
22 );
23
24 $poe_kernel->run;
25 exit 0;
26
27 sub setup_service {
28 my $kernel = $_[KERNEL];
29 $kernel->alias_set( 'MyServer' );
30 $kernel->post( 'MySOAP', 'ADDMETHOD', 'MyServer', 'Sum_Things' );
31 }
32
33 sub shutdown_service {
34 $_[KERNEL]->post( 'MySOAP', 'DELMETHOD', 'MyServer', 'Sum_Things' );
35 }
36
37 sub do_sum {
38 my $response = $_[ARG0];
39 my $params = $response->soapbody;
40 my $sum = 0;
41 while (my ($field, $value) = each(%$params)) {
42 $sum += $value;
43 }
44
45 # Fake an error
46 if ( $sum < 100 ) {
47 $_[KERNEL]->post( 'MySOAP', 'FAULT', $response, 'Client.Add.Error', 'The sum must be above 100' );
48 } else {
49 # Add the content
50 $response->content( "Thanks. Sum is: $sum" );
51 $_[KERNEL]->post( 'MySOAP', 'DONE', $response );
52 }
53 }
54
55ABSTRACT
56 An easy to use SOAP/1.1 daemon for POE-enabled programs
57
58DESCRIPTION
59 This module makes serving SOAP/1.1 requests a breeze in POE.
60
61 The hardest thing to understand in this module is the SOAP Body. That's
62 it!
63
64 The standard way to use this module is to do this:
65
66 use POE;
67 use POE::Component::Server::SOAP;
68
69 POE::Component::Server::SOAP->new( ... );
70
71 POE::Session->create( ... );
72
73 POE::Kernel->run();
74
75 POE::Component::Server::SOAP is a bolt-on component that can publish
76 event handlers via SOAP over HTTP. Currently, this module only supports
77 SOAP/1.1 requests, work will be done in the future to support SOAP/1.2
78 requests. The HTTP server is done via
79 POE::Component::Server::SimpleHTTP.
80
81 Starting Server::SOAP
82 To start Server::SOAP, just call it's new method:
83
84 POE::Component::Server::SOAP->new(
85 'ALIAS' => 'MySOAP',
86 'ADDRESS' => '192.168.1.1',
87 'PORT' => 11111,
88 'HOSTNAME' => 'MySite.com',
89 'HEADERS' => {},
90 );
91
92 This method will die on error or return success.
93
94 This constructor accepts only 7 options.
95
96 "ALIAS"
97 This will set the alias Server::SOAP uses in the POE Kernel. This
98 will default to "SOAPServer"
99
100 "ADDRESS"
101 This value will be passed to POE::Component::Server::SimpleHTTP to
102 bind to.
103
104 Examples: ADDRESS => 0 # Bind to all addresses + localhost ADDRESS
105 => 'localhost' # Bind to localhost ADDRESS => '192.168.1.1' # Bind
106 to specified IP
107
108 "PORT"
109 This value will be passed to POE::Component::Server::SimpleHTTP to
110 bind to.
111
112 "HOSTNAME"
113 This value is for the HTTP::Request's URI to point to. If this is
114 not supplied, POE::Component::Server::SimpleHTTP will use
115 Sys::Hostname to find it.
116
117 "HEADERS"
118 This should be a hashref, that will become the default headers on
119 all HTTP::Response objects. You can override this in individual
120 requests by setting it via $response->header( ... )
121
122 The default header is: Server => 'POE::Component::Server::SOAP/' .
123 $VERSION
124
125 For more information, consult the HTTP::Headers module.
126
127 "MUSTUNDERSTAND"
128 This is a boolean value, controlling whether Server::SOAP will check
129 for this value in the Headers and Fault if it is present. This will
130 default to true.
131
132 "SIMPLEHTTP"
133 This allows you to pass options to the SimpleHTTP backend. One of
134 the real reasons is to support SSL in Server::SOAP, yay! To learn
135 how to use SSL, please consult the
136 POE::Component::Server::SimpleHTTP documentation. Of course, you
137 could totally screw up things, just use this with caution :)
138
139 You must pass a hash reference as the value, because it will be
140 expanded and put in the Server::SimpleHTTP->new() constructor.
141
142 Events
143 There are only a few ways to communicate with Server::SOAP.
144
145 "ADDMETHOD"
146 This event accepts four arguments:
147 - The intended session alias
148 - The intended session event
149 - The public service name ( not required -> defaults to session alias )
150 - The public method name ( not required -> defaults to session event )
151
152 Calling this event will add the method to the registry.
153
154 NOTE: This will overwrite the old definition of a method if it exists!
155
156 "DELMETHOD"
157 This event accepts two arguments:
158 - The service name
159 - The method name
160
161 Calling this event will remove the method from the registry.
162
163 NOTE: if the service now contains no methods, it will also be removed.
164
165 "DELSERVICE"
166 This event accepts one argument:
167 - The service name
168
169 Calling this event will remove the entire service from the registry.
170
171 "DONE"
172 This event accepts only one argument: the SOAP::Response object we sent to the handler.
173
174 Calling this event implies that this particular request is done, and will proceed to close the socket.
175
176 The content in $response->content() will be automatically serialized via SOAP::Lite's SOAP::Serializer
177
178 NOTE: This method automatically sets some parameters:
179 - HTTP Status = 200 ( if not defined )
180 - HTTP Header value of 'Content-Type' = 'text/xml'
181
182 To get greater throughput and response time, do not post() to the DONE event, call() it!
183 However, this will force your program to block while servicing SOAP requests...
184
185 "RAWDONE"
186 This event accepts only one argument: the SOAP::Response object we sent to the handler.
187
188 Calling this event implies that this particular request is done, and will proceed to close the socket.
189
190 The only difference between this and the DONE event is that the content in $response->content() will not
191 be serialized and passed through intact to the SOAP envelope. This is useful if you generate the xml yourself.
192
193 NOTE:
194 - The xml content does not need to have a <?xml version="1.0" encoding="UTF-8"> header
195 - In SOAP::Lite, the client sees '<foo>54</foo><bar>89</bar>' as '54' only!
196 The solution is to enclose the xml in another name, i.e. '<data><foo>54</foo><bar>89</bar></data>'
197 - If the xml is malformed or is not escaped properly, the client will get terribly confused!
198
199 It will be inserted here:
200 ...<soap:Body><namesp4:TestResponse xmlns:namesp4="http://localhost:32080/">YOURSTUFFHERE</namesp4:TestResponse></soap:Body>...
201
202 "FAULT"
203 This event accepts five arguments:
204 - the HTTP::Response object we sent to the handler
205 - SOAP Fault Code ( not required -> defaults to 'Server' )
206 - SOAP Fault String ( not required -> defaults to 'Application Faulted' )
207 - SOAP Fault Detail ( not required )
208 - SOAP Fault Actor ( not required )
209
210 Again, calling this event implies that this particular request is done, and will proceed to close the socket.
211
212 Calling this event will generate a SOAP Fault and return it to the client.
213
214 NOTE: This method automatically sets some parameters:
215 - HTTP Status = 500 ( if not defined )
216 - HTTP Header value of 'Content-Type' = 'text/xml'
217 - HTTP Content = SOAP Envelope of the fault ( overwriting anything that was there )
218
219 "RAWFAULT"
220 This event accepts only one argument: the SOAP::Response object we sent to the handler.
221
222 Calling this event implies that this particular request is done, and will proceed to close the socket.
223
224 The only difference between this and the FAULT event is that you are given freedom to create your own xml for the
225 fault. It will be passed through intact to the SOAP envelope. Be sure to read the SOAP specs :)
226
227 This is very similar to the RAWDONE event, so go read the notes up there!
228
229 It will be inserted here:
230 ...<soap:Body>YOURSTUFFHERE</soap:Body>...
231
232 "CLOSE"
233 This event accepts only one argument: the SOAP::Response object we sent to the handler.
234
235 Calling this event will proceed to close the socket, not sending any output.
236
237 "STARTLISTEN"
238 Starts the listening socket, if it was shut down
239
240 "STOPLISTEN"
241 Simply a wrapper for SHUTDOWN GRACEFUL, but will not shutdown Server::SOAP if there is no more requests
242
243 "SHUTDOWN"
244 Without arguments, Server::SOAP does this:
245 Close the listening socket
246 Kills all pending requests by closing their sockets
247 Removes it's alias
248
249 With an argument of 'GRACEFUL', Server::SOAP does this:
250 Close the listening socket
251 Waits for all pending requests to come in via DONE/FAULT/CLOSE, then removes it's alias
252
253 Processing Requests
254 if you're new to the world of SOAP, reading the documentation by the
255 excellent author of SOAP::Lite is recommended! It also would help to
256 read some stuff at http://www.soapware.org/ -> they have some excellent
257 links :)
258
259 Now, once you have set up the services/methods, what do you expect from
260 Server::SOAP? Every request is pretty straightforward, you just get a
261 Server::SOAP::Response object in ARG0.
262
263 The Server::SOAP::Response object contains a wealth of information about the specified request:
264 - There is the SimpleHTTP::Connection object, which gives you connection information
265 - There is the various SOAP accessors provided via Server::SOAP::Response
266 - There is the HTTP::Request object
267
268 Example information you can get:
269 $response->connection->remote_ip() # IP of the client
270 $response->soaprequest->uri() # Original URI
271 $response->soapmethod() # The SOAP method that was called
272 $response->soapbody() # The arguments to the method
273
274 Probably the most important part of SOAP::Response is the body of the
275 message, which contains the arguments to the method call. The data in
276 the body is a hash, for more information look at SOAP::Lite ->
277 SOAP::Deserializer.
278
279 I cannot guarantee what will be in the body, it is all up to the SOAP
280 serializer/deserializer. I can provide some examples:
281
282 NOTE: It is much easier to play around with parameters if they are properly encoded.
283 If you are using SOAP::Lite, make extensive use of SOAP::Data->name() to create parameters :)
284
285 Calling a SOAP method with no arguments:
286 print SOAP::Lite
287 -> uri('http://localhost:32080/')
288 -> proxy('http://localhost:32080/?session=MyServer')
289 -> Sum_Things()
290 -> result
291
292 The body will look like this:
293 $VAR1 = undef;
294
295 Calling a SOAP method with multiple arguments:
296 print SOAP::Lite
297 -> uri('http://localhost:32080/')
298 -> proxy('http://localhost:32080/?session=MyServer')
299 -> Sum_Things( 8, 6, 7, 5, 3, 0, 9, 183 )
300 -> result
301
302 The body will look like this:
303 $VAR1 = {
304 'c-gensym17' => '183',
305 'c-gensym5' => '6',
306 'c-gensym13' => '0',
307 'c-gensym11' => '3',
308 'c-gensym15' => '9',
309 'c-gensym9' => '5',
310 'c-gensym3' => '8',
311 'c-gensym7' => '7'
312 };
313
314 NOTE: The original array ordering can be received by sorting on the keys.
315
316 Calling a SOAP method with an arrayref
317 print SOAP::Lite
318 -> uri('http://localhost:32080/')
319 -> proxy('http://localhost:32080/?session=MyServer')
320 -> Sum_Things(
321 [ 8, 6, 7, 5, 3, 0, 9, 183 ]
322 )
323 -> result
324
325 The body will look like this:
326 $VAR1 = {
327 'Array' => [
328 '8',
329 '6',
330 '7',
331 '5',
332 '3',
333 '0',
334 '9',
335 '183'
336 ]
337 };
338
339 Calling a SOAP method with a hash:
340 print SOAP::Lite
341 -> uri('http://localhost:32080/')
342 -> proxy('http://localhost:32080/?session=MyServer')
343 -> Sum_Things( {
344 'FOO' => 'bax',
345 'Hello' => 'World!',
346 } )
347 -> result
348
349 The body will look like this:
350 $VAR1 = {
351 'c-gensym21' => {
352 'Hello' => 'World!',
353 'FOO' => 'bax',
354 }
355 };
356
357 Calling a SOAP method using SOAP::Data methods:
358 print SOAP::Lite
359 -> uri('http://localhost:32080/')
360 -> proxy('http://localhost:32080/?session=MyServer')
361 -> Sum_Things(
362 SOAP::Data->name( 'Foo', 'harz' ),
363 SOAP::Data->name( 'Param', 'value' ),
364 )-> result
365
366 The body will look like this:
367 $VAR1 = {
368 'Param' => 'value',
369 'Foo' => 'harz'
370 };
371
372 Simply experiment using Data::Dumper and you'll quickly get the hang of
373 it!
374
375 When you're done with the SOAP request, stuff whatever output you have
376 into the content of the response object.
377
378 $response->content( 'The result is ... ' );
379
380 The only thing left to do is send it off to the DONE event :)
381
382 $_[KERNEL]->post( 'MySOAP', 'DONE', $response );
383
384 If there's an error, you can send it to the FAULT event, which will
385 convert it into a SOAP fault.
386
387 # See this website for more details about what "SOAP Fault" is :)
388 # http://www.w3.org/TR/2000/NOTE-SOAP-20000508/#_Toc478383507
389
390 $_[KERNEL]->post( 'MySOAP', 'FAULT', $response, 'Client.Authentication', 'Invalid password' );
391
392 Server::SOAP Notes
393 This module is very picky about capitalization!
394
395 All of the options are uppercase, to avoid confusion.
396
397 You can enable debugging mode by doing this:
398
399 sub POE::Component::Server::SOAP::DEBUG () { 1 }
400 use POE::Component::Server::SOAP;
401
402 In the case you want to see the raw xml being received/sent to the
403 client, set DEBUG to 2.
404
405 Yes, I broke a lot of things in the release ( 1.01 ), but Rocco agreed
406 that it's best to break things as early as possible, so that development
407 can move on instead of being stuck on legacy issues.
408
409 Using SSL
410 So you want to use SSL in Server::SOAP? Here's a example on how to do
411 it:
412
413 POE::Component::Server::SOAP->new(
414 ...
415 'SIMPLEHTTP' => {
416 'SSLKEYCERT' => [ 'public-key.pem', 'public-cert.pem' ],
417 },
418 );
419
420 # And that's it provided you've already created the necessary key + certificate file :)
421
422 Ah, to use SSL in SOAP::Lite, simply use https://blah.com instead of
423 http://blah.com
424
425SUPPORT
426 You can find documentation for this module with the perldoc command.
427
428 perldoc POE::Component::Server::SOAP
429
430 Websites
431 * AnnoCPAN: Annotated CPAN documentation
432
433 <http://annocpan.org/dist/POE-Component-Server-SOAP>
434
435 * CPAN Ratings
436
437 <http://cpanratings.perl.org/d/POE-Component-Server-SOAP>
438
439 * RT: CPAN's request tracker
440
441 <http://rt.cpan.org/NoAuth/Bugs.html?Dist=POE-Component-Server-SOAP>
442
443 * Search CPAN
444
445 <http://search.cpan.org/dist/POE-Component-Server-SOAP>
446
447 Bugs
448 Please report any bugs or feature requests to
449 "bug-poe-component-server-soap at rt.cpan.org", or through the web
450 interface at
451 <http://rt.cpan.org/NoAuth/ReportBug.html?Queue=POE-Component-Server-SOA
452 P>. I will be notified, and then you'll automatically be notified of
453 progress on your bug as I make changes.
454
455SEE ALSO
456 The examples directory that came with this component.
457
458 POE
459
460 HTTP::Response
461
462 HTTP::Request
463
464 POE::Component::Server::SOAP::Response
465
466 POE::Component::Server::SimpleHTTP
467
468 SOAP::Lite
469
470 POE::Component::SSLify
471
472AUTHOR
473 Apocalypse <apocal@cpan.org>
474
475 I took over this module from Rocco Caputo. Here is his stuff:
476
477 POE::Component::Server::SOAP is Copyright 2002 by Rocco Caputo. All
478 rights are reserved. POE::Component::Server::SOAP is free software;
479 you may redistribute it and/or modify it under the same terms as Perl
480 itself.
481
482 Rocco may be contacted by e-mail via rcaputo@cpan.org.
483
484COPYRIGHT AND LICENSE
485 Copyright 2009 by Apocalypse
486
487 This library is free software; you can redistribute it and/or modify it
488 under the same terms as Perl itself.
489
490