|
NAMECatalyst::Controller::SOAP - Catalyst SOAP ControllerSYNOPSISpackage MyApp::Controller::Example; use base 'Catalyst::Controller::SOAP'; # When using a WSDL, you can just specify the Port name, and it # will infer the style and use. To do that, you just need to use # the WSDLPort attribute. This might be required if your service # has more than one port. This operation will be made available # using the path part of the location attribute of the port # definition. __PACKAGE__->config->{wsdl} = 'file.wsdl'; sub servicefoo : WSDLPort('ServicePort') {} # available in "/example" as operation "ping". The arguments are # treated as a literal document and passed to the method as a # XML::LibXML object # Using XML::Compile here will help you reading the message. sub ping : SOAP('RPCLiteral') { my ( $self, $c, $xml) = @_; my $name = $xml->findValue('some xpath expression'); } # avaiable as "/example/world" in document context. The entire body # is delivered to the method as a XML::LibXML object. # Using XML::Compile here will help you reading the message. sub world :Local SOAP('DocumentLiteral') { my ($self, $c, $xml) = @_; } # avaiable as "/example/get" in HTTP get context. # the get attributes will be available as any other # get operation in Catalyst. sub get :Local SOAP('HTTPGet') { my ($self, $c) = @_; } # this is the endpoint from where the RPC operations will be # dispatched. This code won't be executed at all. # See Catalyst::Controller::SOAP::RPC. sub index :Local SOAP('RPCEndpoint') {} ABSTACTImplements SOAP serving support in Catalyst.DESCRIPTIONSOAP Controller for Catalyst which we tried to make compatible with the way Catalyst works with URLS.It is important to notice that this controller declares by default an index operation which will dispatch the RPC operations under this class.ATTRIBUTESThis class implements the SOAP attribute wich is used to do the mapping of that operation to the apropriate action class. The name of the class used is formed as Catalyst::Action::SOAP::$value, unless the parameter of the attribute starts with a '+', which implies complete namespace.The implementation of SOAP Action classes helps delivering specific SOAP scenarios, like HTTP GET, RPC Encoded, RPC Literal or Document Literal, or even Document RDF or just about any required combination. See Catalyst::Action::SOAP::DocumentLiteral for an example. ACCESSORSOnce you tagged one of the methods, you'll have an $c->stash->{soap} accessor which will return an "Catalyst::Controller::SOAP::Helper" object. It's important to notice that this is achieved by the fact that all the SOAP Action classes are subclasses of Catalyst::Action::SOAP, which implements most of that.You can query this object as follows:
USING WSDLIf you define the "wsdl" configuration key, Catalyst::Controller::SOAP will automatically map your operations into the WSDL operations, in which case you will receive the parsed Perl structure as returned by XML::Compile according to the type defined in the WSDL message.You can define additional wsdl files or even additional schema files. If $wsdl is an arrayref, the first element is the one passed to new, and the others will be the argument to subsequent addWsdl calls. If $wsdl is a hashref, the "wsdl" key will be handled like above and the "schema" key will be used to importDefinitions. If the content of the schema key is an arrayref, it will result in several calls to importDefinition. When using WSDL, you can use the WSDLPort attribute, that not only sets the port name but also infer which is the style of the binding, the use of the input body and also declares the Path for the operation according to the 'location' attribute in the WSDL file. For RPC operations, the endpoint action will be created dinamically also in the path defined by the WSDL file. This is the most convenient way of defining a SOAP service, which, in the end, will require you to have it as simple as: package SOAPApp::Controller::WithWSDL; use base 'Catalyst::Controller::SOAP'; __PACKAGE__->config->{wsdl} = 't/hello4.wsdl'; # in this case, the input has two parts, named 'who' and 'greeting' # and the output has a single 'greeting' part. sub Greet : WSDLPort('Greet') { my ( $self, $c, $args ) = @_; my $who = $args->{who}; my $grt = $args->{greeting}; $c->stash->{soap}->compile_return({ greeting => $grt.' '.$who.'!' }); } When using WSDL with more than one port, the use of this attribute is mandatory. When the WSDL describes more than one service, the controller can only represent one of them, so you must define the 'wsdlservice' config key that will be used to select the service. Also, when using wsdl, you can define the response using: $c->stash->{soap}->compile_return($perl_structure) In this case, the given structure will be transformed by XML::Compile, according to what's described in the WSDL file. If you define "xml_compile" as a configuration key (which is a hashref with keys 'reader' and 'writer', which both have a hashref as their value), those key / value pairs will be passed as options to the XML::Compile::Schema::compile() method. __PACKAGE__->config->{xml_compile} = { reader => {sloppy_integers => 1}, writer => {sloppy_integers => 1}, }; Support for Document/Literal-WrappedPlease make sure you read the documentation at Catalyst::Action::SOAP::DocumentLiteralWrapped before using this feature.The support for Document/Literal-Wrapped works by faking RPC style even when the WSDL says the service is in the "Document" mode. The parameter used for the actual dispatch is the soapAction attribute. In practice, the endpoint of the action is an empty action that will redirect the request to the actual action based on the name of the soapAction. It uses the soap_action_prefix controller configuration variable to extract the name of the action. There is an important restriction in that fact. The name of the operation in the WSDL must match the suffix of the soapAction attribute. If you have a Document/Literal-Wrapped WSDL and rewriting it as RPC/Literal is not an option, take the following steps:
But always try to refactor your WSDL as RPC/Literal instead, which is much more predictable and, in fact, is going to provide you a much more sane WSDL file. USING WSDL AND Catalyst::TestIf you'd like to use the built-in server from Catalyst::Test with your WSDL file (which likely defines an <address location="..."> that differs from the standard test server) you'll need to use the transport_hook option available with $wsdl->compileClient() in your test file.# t/soap_message.t use XML::Compile::WSDL11; use XML::Compile::Transport::SOAPHTTP; use Test::More 'no_plan'; BEGIN { use_ok 'Catalyst::Test', 'MyServer'; } sub proxy_to_test_app { my ($request, $trace) = @_; # request() is a function inserted by Catalyst::Test which # sends HTTP requests to the just-started test server. return request($request); } my $xml = '/path/to/wsdl/file'; my $message = 'YourMessage'; my $port_name = 'YourPort'; my $wsdl = XML::Compile::WSDL11->new($xml); my $client = $wsdl->compileClient($message, port => $port_name, transport_hook => \&proxy_to_test_app, ); $client->(...); TODONo header features are implemented yet.The SOAP Encoding support is also missing, when that is ready you'll be able to do something like the code below: # available in "/example" as operation "echo" # parsing the arguments as soap-encoded. sub echo : SOAP('RPCEncoded') { my ( $self, $c, @args ) = @_; } SEE ALSOCatalyst::Action::SOAP, XML::LibXML, XML::Compile Catalyst::Action::SOAP::DocumentLiteral, Catalyst::Action::SOAP::RPCLiteral, Catalyst::Action::SOAP::HTTPGet, XML::Compile::WSDL11, XML::Compile::SchemaAUTHORSDaniel Ruoso "daniel@ruoso.com"Drew Taylor "drew@drewtaylor.com" Georg Oechsler "goe-cpan@space.net" BUG REPORTSPlease submit all bugs regarding "Catalyst::Controller::SOAP" to "bug-catalyst-controller-soap@rt.cpan.org"LICENSEThis library is free software, you can redistribute it and/or modify it under the same terms as Perl itself.
Visit the GSP FreeBSD Man Page Interface. |