[Catalyst-commits] r7562 - in Catalyst-Controller-SOAP/1.0/trunk:
lib/Catalyst/Controller t t/PostApp/lib/PostApp/Controller
ruoso at dev.catalyst.perl.org
ruoso at dev.catalyst.perl.org
Fri Apr 4 19:04:57 BST 2008
Author: ruoso
Date: 2008-04-04 19:04:56 +0100 (Fri, 04 Apr 2008)
New Revision: 7562
Added:
Catalyst-Controller-SOAP/1.0/trunk/t/PostApp/lib/PostApp/Controller/WithWSDL3.pm
Catalyst-Controller-SOAP/1.0/trunk/t/hello3.wsdl
Modified:
Catalyst-Controller-SOAP/1.0/trunk/lib/Catalyst/Controller/SOAP.pm
Catalyst-Controller-SOAP/1.0/trunk/t/PostApp.t
Log:
[C-C-SOAP] Support for the WSDLPort attribute... Still some things to clear...
Modified: Catalyst-Controller-SOAP/1.0/trunk/lib/Catalyst/Controller/SOAP.pm
===================================================================
--- Catalyst-Controller-SOAP/1.0/trunk/lib/Catalyst/Controller/SOAP.pm 2008-04-04 16:09:50 UTC (rev 7561)
+++ Catalyst-Controller-SOAP/1.0/trunk/lib/Catalyst/Controller/SOAP.pm 2008-04-04 18:04:56 UTC (rev 7562)
@@ -7,18 +7,42 @@
use UNIVERSAL qw(isa);
use constant NS_SOAP_ENV => "http://schemas.xmlsoap.org/soap/envelope/";
+ use constant NS_WSDLSOAP => "http://schemas.xmlsoap.org/wsdl/soap/";
- our $VERSION = '0.6';
+ our $VERSION = '0.7';
- __PACKAGE__->mk_accessors qw(wsdlobj decoders encoders);
+ __PACKAGE__->mk_accessors qw(wsdlobj decoders encoders ports);
- sub _parse_SOAP_attr {
- my ($self, $c, $name, $value) = @_;
+ # XXX - This is here as a temporary fix for
+ sub _parse_attrs {
+ my ( $self, $c, $name, @attrs ) = @_;
+ my @others = grep { $_ !~ /^WSDLPort/ } @attrs;
+ my $final = $self->SUPER::_parse_attrs($c, $name, @others);
+
+
+ my ($attr) = grep { $_ && $_ =~ /^WSDLPort/ } @attrs;
+ return $final unless $attr;
+
+ if ( my ( $key, $value ) = ( $attr =~ /^(.*?)(?:\(\s*(.+?)\s*\))?$/ ) ) #* emacs bug
+ {
+ if ( defined $value ) {
+ ( $value =~ s/^'(.*)'$/$1/ ) || ( $value =~ s/^"(.*)"/$1/ );
+ }
+ my %ret = $self->_parse_WSDLPort_attr($c, $name, $value);
+ push( @{ $final->{$_} }, $ret{$_} ) for
+ keys %ret;
+ }
+
+
+ return $final;
+ }
+
+
+ sub __init_wsdlobj {
+ my ($self, $c) = @_;
+
my $wsdlfile = $self->config->{wsdl};
- my $compile_opts = $self->config->{xml_compile} || {};
- $compile_opts->{reader} ||= {};
- $compile_opts->{writer} ||= {};
if ($wsdlfile) {
if (!$self->wsdlobj) {
@@ -42,8 +66,67 @@
$self->wsdlobj->importDefinitions($schema)
}
}
+ }
- my $operation = $self->wsdlobj->operation($name)
+ return $self->wsdlobj ? 1 : 0;
+ }
+
+ sub _parse_WSDLPort_attr {
+ my ($self, $c, $name, $value) = @_;
+
+ die 'Cannot use WSDLPort without WSDL.'
+ unless $self->__init_wsdlobj;
+
+ $self->ports({}) unless $self->ports();
+ $self->ports->{$name} = $value;
+ my $operation = $self->wsdlobj->operation($name,
+ port => $value,
+ service => $self->config->{wsdlservice})
+ or die 'Every operation should be on the WSDL when using one.';
+
+ # TODO: Use more intelligence when selecting the address.
+ my ($path) = $operation->endPointAddresses();
+
+ $path =~ s#^[^:]+://[^/]+##;
+
+ # Finding out the style and input body use for this operation
+ my $binding = $self->wsdlobj->find(binding => $operation->port->{binding});
+ my $style = $binding->{'{'.NS_WSDLSOAP.'}binding'}[0]->getAttribute('style');
+ my ($use) = map { $_->{input}{'{'.NS_WSDLSOAP.'}body'}[0]->getAttribute('use') }
+ grep { $_->{name} eq $name } @{ $binding->{operation} || [] };
+
+ $style = $style =~ /document/i ? 'Document' : 'RPC';
+ $use = $use =~ /literal/i ? 'Literal' : 'Encoded';
+
+ if ($style eq 'Document') {
+ return
+ (
+ Path => $path,
+ $self->_parse_SOAP_attr($c, $name, $style.$use)
+ )
+ } else {
+ return $self->_parse_SOAP_attr($c, $name, $style.$use)
+ }
+ }
+
+ sub _parse_SOAP_attr {
+ my ($self, $c, $name, $value) = @_;
+
+ my $wsdlfile = $self->config->{wsdl};
+ my $wsdlservice = $self->config->{wsdl_service};
+ my $compile_opts = $self->config->{xml_compile} || {};
+ $compile_opts->{reader} ||= {};
+ $compile_opts->{writer} ||= {};
+
+ if ($wsdlfile) {
+
+ die 'WSDL initialization failed.'
+ unless $self->__init_wsdlobj;
+
+ $self->ports({}) unless $self->ports();
+ my $operation = $self->wsdlobj->operation($name,
+ port => $self->ports->{$name},
+ service => $wsdlservice)
or die 'Every operation should be on the WSDL when using one.';
my $portop = $operation->portOperation();
@@ -251,6 +334,17 @@
# See Catalyst::Controller::SOAP::RPC.
sub index :Local SOAP('RPCEndpoint') {}
+ # 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 instead of the SOAP attribute. This might
+ # be required if your service has more than one port. When using
+ # this attribute with document-style bindings, this operation will
+ # be made available using the path part of the location attribute
+ # of the port definition. This attribute must be used for RPC
+ # operations too, but you still need to define the RPCEndpoint.
+ sub servicefoo : WSDLPort('ServicePort') {}
+
+
=head1 ABSTACT
Implements SOAP serving support in Catalyst.
@@ -344,10 +438,32 @@
the schema key is an arrayref, it will result in several calls to
importDefinition.
-Also, when using wsdl, you can also define the response using
+When using WSDL with more than one service or port,
+XML::Compile::WSDL11 needs extra hints. You should:
=over
+=item __PACKAGE__->config->{wsdlservice} = 'ServiceName'
+
+This option is required whenever your WSDL have more than one service.
+
+=item sub foo : WSDLPort('PortName') { }
+
+When the service has more than one port, you must set the port
+name. For your convenince, the WSDLPort attribute not only sets it but
+also infer which is the style of the binding and the use of the input
+body. If this is a Document-style binding, it will also declare the
+Path for this operation based on the location of the port.
+
+RPC bindings must also use this attribute in multi-port WSDLs, but it
+won't declare the path for this operation and you still
+
+=back
+
+Also, when using wsdl, you can define the response using:
+
+=over
+
=item $c->stash->{soap}->compile_return($perl_structure)
In this case, the given structure will be transformed by XML::Compile,
Added: Catalyst-Controller-SOAP/1.0/trunk/t/PostApp/lib/PostApp/Controller/WithWSDL3.pm
===================================================================
--- Catalyst-Controller-SOAP/1.0/trunk/t/PostApp/lib/PostApp/Controller/WithWSDL3.pm (rev 0)
+++ Catalyst-Controller-SOAP/1.0/trunk/t/PostApp/lib/PostApp/Controller/WithWSDL3.pm 2008-04-04 18:04:56 UTC (rev 7562)
@@ -0,0 +1,23 @@
+package PostApp::Controller::WithWSDL3;
+
+use strict;
+use warnings;
+use base 'Catalyst::Controller::SOAP';
+
+__PACKAGE__->config->{wsdl} = 't/hello3.wsdl';
+
+sub Greet : WSDLPort('Greet') {
+ my ( $self, $c, $args ) = @_;
+ my $who = $args->{parameters}{who};
+ my $grt = $args->{parameters}{greeting};
+ $c->stash->{soap}->compile_return({ details => { greeting => $grt.' '.$who.'!' }});
+}
+
+sub Shout : WSDLPort('Shout') {
+ my ( $self, $c, $args ) = @_;
+ my $who = $args->{parameters}{who};
+ my $grt = $args->{parameters}{greeting};
+ $c->stash->{soap}->compile_return({ details => {greeting => uc($grt).' '.uc($who).'!!' }});
+}
+
+1;
Modified: Catalyst-Controller-SOAP/1.0/trunk/t/PostApp.t
===================================================================
--- Catalyst-Controller-SOAP/1.0/trunk/t/PostApp.t 2008-04-04 16:09:50 UTC (rev 7561)
+++ Catalyst-Controller-SOAP/1.0/trunk/t/PostApp.t 2008-04-04 18:04:56 UTC (rev 7562)
@@ -1,4 +1,4 @@
-use Test::More tests => 9;
+use Test::More tests => 11;
use File::Spec::Functions;
use HTTP::Response;
use IPC::Open3;
@@ -87,7 +87,35 @@
like($response->content, qr/Fault/, 'Fault for uncaugh exception: '.$response->content);
# diag("/ws/bar: ".$response->content);
+$response = soap_xml_post
+ ('/hello/Greet',
+ '<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">
+ <Body>
+ <GreetingSpecifier>
+ <who>World</who>
+ <greeting>Hello</greeting>
+ </GreetingSpecifier>
+ </Body>
+ </Envelope>'
+ );
+like($response->content, qr/greeting\>Hello World\!\<\//, ' using WSDLPort response: '.$response->content);
+# diag("/withwsdl/Greet: ".$response->content);
+$response = soap_xml_post
+ ('/hello/Shout',
+ '<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">
+ <Body>
+ <GreetingSpecifier>
+ <who>World</who>
+ <greeting>Hello</greeting>
+ </GreetingSpecifier>
+ </Body>
+ </Envelope>'
+ );
+like($response->content, qr/greeting\>HELLO WORLD\!\!\<\//, ' using WSDLPort response: '.$response->content);
+# diag("/withwsdl/Shout: ".$response->content);
+
+
sub soap_xml_post {
my $path = shift;
my $content = shift;
Added: Catalyst-Controller-SOAP/1.0/trunk/t/hello3.wsdl
===================================================================
--- Catalyst-Controller-SOAP/1.0/trunk/t/hello3.wsdl (rev 0)
+++ Catalyst-Controller-SOAP/1.0/trunk/t/hello3.wsdl 2008-04-04 18:04:56 UTC (rev 7562)
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<wsdl:definitions
+ xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
+ xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
+ xmlns:s="http://www.w3.org/2001/XMLSchema"
+ xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
+ xmlns:hello="http://example.com/hello"
+ xmlns="http://example.com/hello"
+ targetNamespace="http://example.com/hello">
+
+ <wsdl:types>
+ <s:schema elementFormDefault="qualified" targetNamespace="http://example.com/hello">
+ <s:element name="GreetingSpecifier">
+ <s:complexType>
+ <s:sequence>
+ <s:element minOccurs="0" maxOccurs="1" name="who" type="s:string"/>
+ <s:element minOccurs="0" maxOccurs="1" name="greeting" type="s:string"/>
+ </s:sequence>
+ </s:complexType>
+ </s:element>
+ <s:element name="GreetingResponse">
+ <s:complexType>
+ <s:sequence>
+ <s:element minOccurs="0" maxOccurs="1" name="greeting" type="s:string"/>
+ </s:sequence>
+ </s:complexType>
+ </s:element>
+ </s:schema>
+ </wsdl:types>
+ <wsdl:message name="AskGreeting">
+ <wsdl:part name="parameters" element="hello:GreetingSpecifier"/>
+ </wsdl:message>
+ <wsdl:message name="GiveGreeting">
+ <wsdl:part name="details" element="hello:GreetingResponse"/>
+ </wsdl:message>
+ <wsdl:portType name="Greeting">
+ <wsdl:operation name="Greet">
+ <wsdl:input message="hello:AskGreeting"/>
+ <wsdl:output message="hello:GiveGreeting"/>
+ </wsdl:operation>
+ </wsdl:portType>
+ <wsdl:portType name="Shouting">
+ <wsdl:operation name="Shout">
+ <wsdl:input message="hello:AskGreeting"/>
+ <wsdl:output message="hello:GiveGreeting"/>
+ </wsdl:operation>
+ </wsdl:portType>
+ <wsdl:binding name="Greeting" type="hello:Greeting">
+ <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/>
+ <wsdl:operation name="Greet">
+ <soap:operation style="document"/>
+ <wsdl:input>
+ <soap:body use="literal"/>
+ </wsdl:input>
+ <wsdl:output>
+ <soap:body use="literal"/>
+ </wsdl:output>
+ </wsdl:operation>
+ </wsdl:binding>
+ <wsdl:binding name="Shouting" type="hello:Shouting">
+ <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/>
+ <wsdl:operation name="Shout">
+ <soap:operation style="document"/>
+ <wsdl:input>
+ <soap:body use="literal"/>
+ </wsdl:input>
+ <wsdl:output>
+ <soap:body use="literal"/>
+ </wsdl:output>
+ </wsdl:operation>
+ </wsdl:binding>
+ <wsdl:service name="Greet">
+ <wsdl:port name="Greet" binding="hello:Greeting">
+ <soap:address location="http://localhost:3000/hello/Greet"/>
+ </wsdl:port>
+ <wsdl:port name="Shout" binding="hello:Shouting">
+ <soap:address location="http://localhost:3000/hello/Shout"/>
+ </wsdl:port>
+ </wsdl:service>
+</wsdl:definitions>
\ No newline at end of file
More information about the Catalyst-commits
mailing list