1# ======================================================================
2#
3# Copyright (C) 2000-2004 Paul Kulchenko (paulclinger@yahoo.com)
4# SOAP::Lite is free software; you can redistribute it
5# and/or modify it under the same terms as Perl itself.
6#
7# $Id: HTTP.pm,v 1.1 2004/10/16 17:45:17 byrnereese Exp $
8#
9# ======================================================================
10
11__END__
12
13=head1 NAME
14
15SOAP::Transport::HTTP - Server/Client side HTTP support for SOAP::Lite
16
17=head1 SYNOPSIS
18
19=over 4
20
21=item Client
22
23  use SOAP::Lite
24    uri => 'http://my.own.site.com/My/Examples',
25    proxy => 'http://localhost/',
26  # proxy => 'http://localhost/cgi-bin/soap.cgi', # local CGI server
27  # proxy => 'http://localhost/',                 # local daemon server
28  # proxy => 'http://localhost/soap',             # local mod_perl server
29  # proxy => 'https://localhost/soap',            # local mod_perl SECURE server
30  # proxy => 'http://login:password@localhost/cgi-bin/soap.cgi', # local CGI server with authentication
31  ;
32
33  print getStateName(1);
34
35=item CGI server
36
37  use SOAP::Transport::HTTP;
38
39  SOAP::Transport::HTTP::CGI
40    # specify path to My/Examples.pm here
41    -> dispatch_to('/Your/Path/To/Deployed/Modules', 'Module::Name', 'Module::method')
42    -> handle
43  ;
44
45=item Daemon server
46
47  use SOAP::Transport::HTTP;
48
49  # change LocalPort to 81 if you want to test it with soapmark.pl
50
51  my $daemon = SOAP::Transport::HTTP::Daemon
52    -> new (LocalAddr => 'localhost', LocalPort => 80)
53    # specify list of objects-by-reference here
54    -> objects_by_reference(qw(My::PersistentIterator My::SessionIterator My::Chat))
55    # specify path to My/Examples.pm here
56    -> dispatch_to('/Your/Path/To/Deployed/Modules', 'Module::Name', 'Module::method')
57  ;
58  print "Contact to SOAP server at ", $daemon->url, "\n";
59  $daemon->handle;
60
61=item Apache mod_perl server
62
63See F<examples/server/Apache.pm> and L</"EXAMPLES"> section for more information.
64
65=item mod_soap server (.htaccess, directory-based access)
66
67  SetHandler perl-script
68  PerlHandler Apache::SOAP
69  PerlSetVar dispatch_to "/Your/Path/To/Deployed/Modules, Module::Name, Module::method"
70  PerlSetVar options "compress_threshold => 10000"
71
72See L<Apache::SOAP> for more information.
73
74=back
75
76=head1 DESCRIPTION
77
78This class encapsulates all HTTP related logic for a SOAP server,
79independent of what web server it's attached to.
80If you want to use this class you should follow simple guideline
81mentioned above.
82
83Following methods are available:
84
85=over 4
86
87=item on_action()
88
89on_action method lets you specify SOAPAction understanding. It accepts
90reference to subroutine that takes three parameters:
91
92  SOAPAction, method_uri and method_name.
93
94C<SOAPAction> is taken from HTTP header and method_uri and method_name are
95extracted from request's body. Default behavior is match C<SOAPAction> if
96present and ignore it otherwise. You can specify you own, for example
97die if C<SOAPAction> doesn't match with following code:
98
99  $server->on_action(sub {
100    (my $action = shift) =~ s/^("?)(.+)\1$/$2/;
101    die "SOAPAction shall match 'uri#method'\n" if $action ne join '#', @_;
102  });
103
104=item dispatch_to()
105
106dispatch_to lets you specify where you want to dispatch your services
107to. More precisely, you can specify C<PATH>, C<MODULE>, C<method> or
108combination C<MODULE::method>. Example:
109
110  dispatch_to(
111    'PATH/',          # dynamic: load anything from there, any module, any method
112    'MODULE',         # static: any method from this module
113    'MODULE::method', # static: specified method from this module
114    'method',         # static: specified method from main::
115  );
116
117If you specify C<PATH/> name of module/classes will be taken from uri as
118path component and converted to Perl module name with substitution
119'::' for '/'. Example:
120
121  urn:My/Examples              => My::Examples
122  urn://localhost/My/Examples  => My::Examples
123  http://localhost/My/Examples => My::Examples
124
125For consistency first '/' in the path will be ignored.
126
127According to this scheme to deploy new class you should put this
128class in one of the specified directories and enjoy its services.
129Easy, eh?
130
131=item handle()
132
133handle method will handle your request. You should provide parameters
134with request() method, call handle() and get it back with response() .
135
136=item request()
137
138request method gives you access to HTTP::Request object which you
139can provide for Server component to handle request.
140
141=item response()
142
143response method gives you access to HTTP::Response object which
144you can access to get results from Server component after request was
145handled.
146
147=back
148
149=head2 PROXY SETTINGS
150
151You can use any proxy setting you use with LWP::UserAgent modules:
152
153 SOAP::Lite->proxy('http://endpoint.server/',
154                   proxy => ['http' => 'http://my.proxy.server']);
155
156or
157
158 $soap->transport->proxy('http' => 'http://my.proxy.server');
159
160should specify proxy server for you. And if you use C<HTTP_proxy_user>
161and C<HTTP_proxy_pass> for proxy authorization SOAP::Lite should know
162how to handle it properly.
163
164=head2 COOKIE-BASED AUTHENTICATION
165
166  use HTTP::Cookies;
167
168  my $cookies = HTTP::Cookies->new(ignore_discard => 1);
169    # you may also add 'file' if you want to keep them between sessions
170
171  my $soap = SOAP::Lite->proxy('http://localhost/');
172  $soap->transport->cookie_jar($cookies);
173
174Cookies will be taken from response and provided for request. You may
175always add another cookie (or extract what you need after response)
176with HTTP::Cookies interface.
177
178You may also do it in one line:
179
180  $soap->proxy('http://localhost/',
181               cookie_jar => HTTP::Cookies->new(ignore_discard => 1));
182
183=head2 SSL CERTIFICATE AUTHENTICATION
184
185To get certificate authentication working you need to specify three
186environment variables: C<HTTPS_CERT_FILE>, C<HTTPS_KEY_FILE>, and
187(optionally) C<HTTPS_CERT_PASS>:
188
189  $ENV{HTTPS_CERT_FILE} = 'client-cert.pem';
190  $ENV{HTTPS_KEY_FILE}  = 'client-key.pem';
191
192Crypt::SSLeay (which is used for https support) will take care about
193everything else. Other options (like CA peer verification) can be specified
194in a similar way. See Crypt::SSLeay documentation for more details.
195
196Those who would like to use encrypted keys may check
197http://groups.yahoo.com/group/soaplite/message/729 for details.
198
199=head2 COMPRESSION
200
201SOAP::Lite provides you with the option for enabling compression on the
202wire (for HTTP transport only). Both server and client should support
203this capability, but this should be absolutely transparent to your
204application. The Server will respond with an encoded message only if
205the client can accept it (indicated by client sending an Accept-Encoding
206header with 'deflate' or '*' values) and client has fallback logic,
207so if server doesn't understand specified encoding
208(Content-Encoding: deflate) and returns proper error code
209(415 NOT ACCEPTABLE) client will repeat the same request without encoding
210and will store this server in a per-session cache, so all other requests
211will go there without encoding.
212
213Having options on client and server side that let you specify threshold
214for compression you can safely enable this feature on both client and
215server side.
216
217=over 4
218
219=item Client
220
221  print SOAP::Lite
222    -> uri('http://localhost/My/Parameters')
223    -> proxy('http://localhost/', options => {compress_threshold => 10000})
224    -> echo(1 x 10000)
225    -> result
226  ;
227
228=item Server
229
230  my $server = SOAP::Transport::HTTP::CGI
231    -> dispatch_to('My::Parameters')
232    -> options({compress_threshold => 10000})
233    -> handle;
234
235=back
236
237Compression will be enabled on the client side
238B<if> the threshold is specified
239B<and> the size of current message is bigger than the threshold
240B<and> the module Compress::Zlib is available.
241
242The Client will send the header 'Accept-Encoding' with value 'deflate'
243B<if> the threshold is specified
244B<and> the module Compress::Zlib is available.
245
246Server will accept the compressed message if the module Compress::Zlib
247is available, and will respond with the compressed message
248B<only if> the threshold is specified
249B<and> the size of the current message is bigger than the threshold
250B<and> the module Compress::Zlib is available
251B<and> the header 'Accept-Encoding' is presented in the request.
252
253=head1 EXAMPLES
254
255Consider following examples of SOAP servers:
256
257=over 4
258
259=item CGI:
260
261  use SOAP::Transport::HTTP;
262
263  SOAP::Transport::HTTP::CGI
264    -> dispatch_to('/Your/Path/To/Deployed/Modules', 'Module::Name', 'Module::method')
265    -> handle
266  ;
267
268=item daemon:
269
270  use SOAP::Transport::HTTP;
271
272  my $daemon = SOAP::Transport::HTTP::Daemon
273    -> new (LocalAddr => 'localhost', LocalPort => 80)
274    -> dispatch_to('/Your/Path/To/Deployed/Modules', 'Module::Name', 'Module::method')
275  ;
276  print "Contact to SOAP server at ", $daemon->url, "\n";
277  $daemon->handle;
278
279=item mod_perl:
280
281httpd.conf:
282
283  <Location /soap>
284    SetHandler perl-script
285    PerlHandler SOAP::Apache
286  </Location>
287
288Apache.pm:
289
290  package SOAP::Apache;
291
292  use SOAP::Transport::HTTP;
293
294  my $server = SOAP::Transport::HTTP::Apache
295    -> dispatch_to('/Your/Path/To/Deployed/Modules', 'Module::Name', 'Module::method');
296
297  sub handler { $server->handler(@_) }
298
299  1;
300
301=item Apache::Registry:
302
303httpd.conf:
304
305  Alias /mod_perl/ "/Apache/mod_perl/"
306  <Location /mod_perl>
307    SetHandler perl-script
308    PerlHandler Apache::Registry
309    PerlSendHeader On
310    Options +ExecCGI
311  </Location>
312
313soap.mod_cgi (put it in /Apache/mod_perl/ directory mentioned above)
314
315  use SOAP::Transport::HTTP;
316
317  SOAP::Transport::HTTP::CGI
318    -> dispatch_to('/Your/Path/To/Deployed/Modules', 'Module::Name', 'Module::method')
319    -> handle
320  ;
321
322=back
323
324WARNING: dynamic deployment with Apache::Registry will fail, because
325module will be loaded dynamically only for the first time. After that
326it is already in the memory, that will bypass dynamic deployment and
327produces error about denied access. Specify both PATH/ and MODULE name
328in dispatch_to() and module will be loaded dynamically and then will work
329as under static deployment. See examples/server/soap.mod_cgi for example.
330
331=head1 TROUBLESHOOTING
332
333=over 4
334
335=item Dynamic libraries are not found
336
337If you see in webserver's log file something like this:
338
339Can't load '/usr/local/lib/perl5/site_perl/.../XML/Parser/Expat/Expat.so'
340for module XML::Parser::Expat: dynamic linker: /usr/local/bin/perl:
341 libexpat.so.0 is NEEDED, but object does not exist at
342/usr/local/lib/perl5/.../DynaLoader.pm line 200.
343
344and you are using Apache web server, try to put into your httpd.conf
345
346 <IfModule mod_env.c>
347     PassEnv LD_LIBRARY_PATH
348 </IfModule>
349
350=item Apache is crashing with segfaults (it may looks like "500 unexpected EOF before status line seen" on client side)
351
352If using SOAP::Lite (or XML::Parser::Expat) in combination with mod_perl
353causes random segmentation faults in httpd processes try to configure
354Apache with:
355
356 RULE_EXPAT=no
357
358-- OR (for Apache 1.3.20 and later) --
359
360 ./configure --disable-rule=EXPAT
361
362See http://archive.covalent.net/modperl/2000/04/0185.xml for more
363details and lot of thanks to Robert Barta <rho@bigpond.net.au> for
364explaining this weird behavior.
365
366If it doesn't help, you may also try -Uusemymalloc
367(or something like that) to get perl to use the system's own malloc.
368Thanks to Tim Bunce <Tim.Bunce@pobox.com>.
369
370=item CGI scripts are not running under Microsoft Internet Information Server (IIS)
371
372CGI scripts may not work under IIS unless scripts are .pl, not .cgi.
373
374=back
375
376=head1 DEPENDENCIES
377
378 Crypt::SSLeay             for HTTPS/SSL
379 SOAP::Lite, URI           for SOAP::Transport::HTTP::Server
380 LWP::UserAgent, URI       for SOAP::Transport::HTTP::Client
381 HTTP::Daemon              for SOAP::Transport::HTTP::Daemon
382 Apache, Apache::Constants for SOAP::Transport::HTTP::Apache
383
384=head1 SEE ALSO
385
386 See ::CGI, ::Daemon and ::Apache for implementation details.
387 See examples/server/soap.cgi as SOAP::Transport::HTTP::CGI example.
388 See examples/server/soap.daemon as SOAP::Transport::HTTP::Daemon example.
389 See examples/My/Apache.pm as SOAP::Transport::HTTP::Apache example.
390
391=head1 COPYRIGHT
392
393Copyright (C) 2000-2001 Paul Kulchenko. All rights reserved.
394
395This library is free software; you can redistribute it and/or modify
396it under the same terms as Perl itself.
397
398=head1 AUTHOR
399
400Paul Kulchenko (paulclinger@yahoo.com)
401
402=cut
403