1=pod 2 3=head1 NAME 4 5SOAP::WSDL::Manual::Cookbook - SOAP::WSDL recipes 6 7=head2 Accessing HTTPS webservices 8 9You need Crypt::SSLeay installed to access HTTPS webservices. 10 11=head2 Accessing protected web services 12 13Passing a username and password, or a client certificate and key, to the 14transport layer is highly dependent on the transport backend. The descriptions 15below are for HTTP(S) transport using LWP::UserAgent 16 17=head3 Accessing HTTP(S) webservices with basic/digest authentication 18 19When using SOAP::WSDL::Transport::HTTP (SOAP::Lite not installed), add a 20method called "get_basic_credentials" to SOAP::WSDL::Transport::HTTP: 21 22 *SOAP::WSDL::Transport::HTTP::get_basic_credentials = sub { 23 return ($user, $password); 24 }; 25 26When using SOAP::Transport::HTTP (SOAP::Lite is installed), do the same to 27this backend: 28 29 *SOAP::Transport::HTTP::Client::get_basic_credentials = sub { 30 return ($user, $password); 31 }; 32 33=head3 Accessing HTTP(S) webservices protected by NTLM authentication 34 35If you want to connect to a windows server using some Windows Domain Login, please 36consider using Kerberos instead of the (older) NTLM mechanism - see below. 37 38Kerberos and NTLM are (currently) mutually exclusive - when LWP::Authen::Negotiate 39is installed, it will always be queried (and will always raise an error), even 40if you don't want to use it. See http://rt.cpan.org/Public/Bug/Display.html?id=32826 41for details. 42 43You need the L<NTLM|NTLM> distribution installed to access webservices protected 44by NTLM authentication. More specifically, you need the Authen::NTLM module 45from this distribution. Note that this is different from the Authen::NTML 46distribution by Yee Man Chan also available from CPAN. 47 48Your user credentials usually need to include the windows domain or the 49windows hostname like this: 50 51 testdomain\testuser 52 53or 54 55 \\testhost\testuser 56 57Besides passing user credentials as when accessing a web service protected 58by basic or digest authentication, you also need to enforce connection 59keep_alive on the transport backens. 60 61To do so, pass a I<proxy> argument to the new() method of the generated 62class. This unfortunately means that you have to set the endpoint URL, too: 63 64 my $interface = MyInterfaces::SERVICE_NAME::PORT_NAME->new({ 65 proxy => [ $url, keep_alive => 1 ] 66 }); 67 68You may, of course, decide to just hack the generated class. Be advised that 69subclassing might be a more appropriate solution - re-generating overwrites 70changes in interface classes. 71 72=head3 Accessing HTTP(S) webservices protected by NTLMv2 73 74There are different variants of NTLM, and by default Authen::NTLM uses the v1 variant. 75 76NTLM is a connection-based handshake authentication protocol, which requires 77three or more requests on the same connection: 78 79 Request POST 80 Response 401 Unauthorized 81 WWW-Authenticate: NTLM 82 83 Request Authorization: NTLM <base64-encoded type-1-message> 84 Response 401 Unauthorized 85 WWW-Authenticate: NTLM <base64-encoded type-2-message> 86 87 Request Authorization: NTLM <base64-encoded type-3-message> 88 Response 200 Ok 89 90If you try to access a NTLMv2 protected web service and switch on LWP::Debug by 91saying 92 93 use LWP::Debug qw(+); 94 95you should see at least two lines containing something like 96 97 Authorization NTLM TlRMTVNTUAABAAAAB7IAAAAAAAAAAAAAAwADACAAAABmb28= 98 ... 99 Authorization NTLM TlRMTVNTUAABAAAAB7IAAAAAAAAAAAAAAw ... much longer ... ADACAAAABmb28= 100 101If you're talking to a Server using NTLMv2 exclusively, you will only the first line 102in the debug output, and then an error. 103 104To explicitly enable NTLMv2, do the following in your client: 105 106 use Authen::NTLM; 107 ntlmv2(1); 108 109This globally enables the use of NTLMv2. Note that this is a global setting: All 110clients running in the same perl interpreter will be affected. This can 111cause unexpected issues when running under mod_perl. 112 113=head3 Accessing webservices protected by HTTP Kerberos Authentication 114 115Use the L<LWP::Authen::Negotiate|LWP::Authen::Negotiate> plugin from CPAN. You 116need to set up GSSAPI to perform the Kerberos authentication, though. How to do 117this is implementation specific (MIT or Heimdahl). See your Kerberos/GSSAPI 118documentation for details. 119 120(Newer) Windows Web Services usually allow one to use both the Negotiate (Kerberos) 121and NTLM authentication scheme. 122 123=head3 Accessing HTTPS webservices protected by certificate authentication 124 125You need Crypt::SSLeay installed to access HTTPS webservices. 126 127See L<Crypt::SSLeay> on how to configure client certificate authentication. 128 129=head1 XML OUTPUT 130 131=head2 Outputting namespaces as prefixes 132 133Q: I need to interface with a SOAP server which doesn't accept the following 134format: 135 136 <SOAP-ENV:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 137 xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> 138 <SOAP-ENV:Body> 139 <getElement xmlns="http://services.company.com/"> 140 <elementId>12345</elementId> 141 </getElement> 142 </SOAP-ENV:Body> 143 </SOAP-ENV:Envelope> 144 145Instead, it requires this: 146 147 <SOAP-ENV:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 148 xmlns:ns2="http://services.company.com/" 149 xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> 150 <SOAP-ENV:Body> 151 <ns2:getElement> 152 <ns2:elementId>12345</ns2:elementId> 153 </ns2:getElement> 154 </SOAP-ENV:Body> 155 </SOAP-ENV:Envelope> 156 157How do I do this using SOAP::WSDL? 158 159A: The following steps are necessary to achieve this result: 160 161First, you would need to write a new serializer, which is quite easy, as it 162just creates the envelope and calls ->serialize_qualified() on $header and 163$body to fill them in. The new serializer has to declare all namespace 164prefixes used, the rest is just the same as the original XSD serializer. 165 166Second, you'd need to overwrite the start_tag method in 167L<SOAP::WSDL::XSD::Typelib::Element|SOAP::WSDL::XSD::Typelib::Element> to use 168the appropriate prefixes for the body elements. 169 170In contrast to the original method, it would probably look up the appropriate 171prefix from some data set in the serializer class, so this could be the 172appropriate place to load SOAP::WSDL::XSD::Typelib::Element and override the 173method. 174 175Something like this should do (without the handling of specialties like empty 176or nil elements): 177 178 %PREFIX_OF = { 'http://services.company.com/' => 'ns2' }; 179 180 *SOAP::WSDL::XSD::Typelib::Element::start_tag = sub { 181 # use prefix instead of xmlns attribute and copy the rest from 182 # SOAP::WSDL::XSD::Typelib::Element::start_tag 183 my $prefix = $PREFIX_OF{ $_[0]->get_xmlns() }; 184 my $name = $_[1]->{ name } || $self->__get_name(); 185 return "<$prefix:$name>"; 186 } 187 188=head1 Skipping unknown XML elements - "lax" XML processing 189 190SOAP::WSDL's default serializer 191L<SOAP::WSDL::Deserializer::XSD|SOAP::WSDL::Deserializer::XSD> is a "strict" 192XML processor in the sense that it throws an exception on encountering unknown 193XML elements. 194 195L<SOAP::WSDL::Deserializer::XSD|SOAP::WSDL::Deserializer::XSD> allows 196switching off the stric XML processing by passing the C<strict =E<gt> 0> 197option. 198 199=head2 Disabling strict XML processing in a Client 200 201Pass the following as C<deserializer_args>: 202 203 { strict => 0 } 204 205Example: The generated SOAP client is assumed to be "MyInterface::Test". 206 207 use MyInterface::Test; 208 209 my $soap = MyInterface::Test->new({ 210 deserializer_args => { strict => 0 } 211 }); 212 213 my $result = $soap->SomeMethod(); 214 215=head2 Disabling strict XML processing in a CGI based server 216 217You have to set the deserializer in the transport class explicitly to 218a L<SOAP::WSDL::Deserializer|SOAP::WSDL::Deserializer> object with the 219C<strict> option set to 0. 220 221Example: The generated SOAP server is assumed to be "MyServer::Test". 222 223 use strict; 224 use MyServer::Test; 225 use SOAP::WSDL::Deserializer::XSD; 226 227 my $soap = MyServer::Test->new({ 228 transport_class => 'SOAP::WSDL::Server::CGI', 229 dispatch_to => 'main', 230 }); 231 $soap->get_transport()->set_deserializer( 232 SOAP::WSDL::Deserializer::XSD->new({ strict => 0 }) 233 ); 234 235 $soap->handle(); 236 237=head2 Disabling strict XML processing in a mod_perl based server 238 239Sorry, this is not implemented yet - you'll have to write your own handler 240class based on L<SOAP::WSDL::Server::Mod_Perl2|SOAP::WSDL::Server::Mod_Perl2>. 241 242=head1 Changing the encoding of a SOAP request 243 244SOAP::WSDL uses utf-8 per default: utf-8 245is the de-facto standard for webservice ommunication. 246 247However, you can change the encoding the transport layer announces by calling 248C<set_encoding($encoding)> on a client object. 249 250You probably have to write your own serializer class too, because the default 251serializer has the utf-8 encoding hardcoded in the envelope. 252 253Just look into SOAP::WSDL::Serializer on how to do that. 254 255Don't forget to register your serializer at the serializer factory 256SOAP::WSDL::Factory::Serializer. 257 258=head1 LICENSE AND COPYRIGHT 259 260Copyright 2008, 2009 Martin Kutter. 261 262This file is part of SOAP-WSDL. You may distribute/modify it under 263the same terms as perl itself. 264 265=head1 AUTHOR 266 267Martin Kutter E<lt>martin.kutter fen-net.deE<gt> 268 269=head1 REPOSITORY INFORMATION 270 271 $Rev: 583 $ 272 $LastChangedBy: kutterma $ 273 $Id: $ 274 $HeadURL: $ 275 276=cut 277