<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1"> <title>gSOAP WS-Addressing: The wsa plugin for stand-alone services</title> <link href="doxygen.css" rel="stylesheet" type="text/css"> </head><body> <!-- Generated by Doxygen 1.3.8 --> <div class="qindex"><a class="qindex" href="index.html">Main Page</a> | <a class="qindex" href="annotated.html">Class List</a> | <a class="qindex" href="files.html">File List</a> | <a class="qindex" href="functions.html">Class Members</a> | <a class="qindex" href="globals.html">File Members</a> | <a class="qindex" href="pages.html">Related Pages</a></div> <h1><a class="anchor" name="wsa">The wsa plugin for stand-alone services</a></h1><h2><a class="anchor" name="wsa_1"> WS-Addressing Setup</a></h2> The material in this section relates to the WS-Addressing specification.<p> To use the wsa plugin:<ol> <li>Run wsdl2h -t typemap.dat on a WSDL of a service that requires WS-Addressing headers. The typemap.dat file included in the gSOAP package is used to recognize and translate Addressing header blocks.</li><li>Run soapcpp2 -a on the header file produced by wsdl2h. To enable addressing-based service operation selection, you MUST use soapcpp2 option -a. This allows the service to dispatch methods based on the WS-Addressing action information header value (assuming the wsa plugin is registered).</li><li>(Re-)compile stdsoap2.c/pp, dom.c/pp, <a class="el" href="wsaapi_8c.html">wsaapi.c</a> and the generated source files.</li><li>Use the wsa plugin API functions described below.</li></ol> <p> An example wsa client/server application can be found in samples/wsa.<p> The header file with a wsa import is automatically generated by wsdl2h for a set of WSDLs that use WS-Addressing. The gSOAP header file is further processed by soapcpp2 to generate the binding code. The wsdl2h-generated header file might include the following imports: <div class="fragment"><pre><span class="preprocessor">#import "soap12.h"</span> <span class="preprocessor">#import "wsa.h"</span> <span class="comment">// or wsa3.h (2003/03), wsa4.h (2004/03), wsa5.h (2005/03)</span> </pre></div>The gSOAP header file is processed with soapcpp2 to generate the client-side and/or server-side binding code.<p> Note that the wsa.h header file located in the import directory of the gSOAP package declares the WS-Addressing information header elements and types. The soap12.h header file enables SOAP 1.2 messaging.<p> For developers: the WS-Addressing header blocks in wsa.h were generated from the WS-Addressing schema with the wsdl2h tool and WS/WS-typemap.dat as follows:<p> <div class="fragment"><pre> $ wsdl2h -cegy -o wsa.h -t WS/WS-typemap.dat WS/WS-Addressing.xsd </pre></div>Refer to wsa.h for more details.<h2><a class="anchor" name="wsa_2"> Client-side Usage</a></h2> <h3><a class="anchor" name="wsa_2_1"> Constructing WS-Addressing Information Headers</a></h3> To associate WS-Addressing information headers with service operations, the SOAP Header struct must have been defined and for each service operation that uses WS-Addressing method-header-part directives should be used in the gSOAP header file of the service as follows: <div class="fragment"><pre><span class="preprocessor">#import "wsa.h"</span> <span class="comment">//gsoap ns service method-header-part: example wsa__MessageID</span> <span class="comment">//gsoap ns service method-header-part: example wsa__RelatesTo</span> <span class="comment">//gsoap ns service method-header-part: example wsa__From</span> <span class="comment">//gsoap ns service method-header-part: example wsa__ReplyTo</span> <span class="comment">//gsoap ns service method-header-part: example wsa__FaultTo</span> <span class="comment">//gsoap ns service method-header-part: example wsa__To</span> <span class="comment">//gsoap ns service method-header-part: example wsa__Action</span> <span class="comment">//gsoap ns service method-action: example urn:example/examplePort/example</span> <span class="keywordtype">int</span> ns__example(<span class="keywordtype">char</span> *in, <span class="keyword">struct</span> ns__exampleResponse *out); </pre></div>Note that the use of wsa versions determines the wsa prefix, e.g. use wsa5 for the latest WS-Addressing as in wsa5__MessageID.<p> In the client-side code, the WS-Addressing information headers are set with <a class="el" href="wsaapi_8h.html#a9">soap_wsa_request()</a> by passing an optional message UUID string, a mandatory destination address URI string, and a mandatory request action URI string. The wsa plugin should be registered with the current soap struct context. An optional source address information header can be added with <a class="el" href="wsaapi_8h.html#a10">soap_wsa_add_From()</a> (must be invoked after the soap_wsa_request call).<p> For example: <div class="fragment"><pre>soap_register_plugin(soap, soap_wsa); <span class="keywordflow">if</span> (<a class="code" href="wsaapi_8h.html#a9">soap_wsa_request</a>(soap, RequestMessageID, ToAddress, RequestAction)) || <a class="code" href="wsaapi_8h.html#a10">soap_wsa_add_From</a>(soap, FromAddress)) <span class="comment">// optional: add a 'From' address</span> ... <span class="comment">// error: out of memory</span> <span class="keywordflow">if</span> (soap_call_ns__example(soap, ToAddress, NULL, ...)) soap_print_fault(soap, stderr); <span class="comment">// an error occurred</span> <span class="keywordflow">else</span> <span class="comment">// process the response </span> </pre></div><h3><a class="anchor" name="wsa_2_2"> Information Headers for Relaying Server Responses</a></h3> To relay the response to another destination, the WS-Addressing ReplyTo information header is added with <a class="el" href="wsaapi_8h.html#a12">soap_wsa_add_ReplyTo()</a> by passing a reply address URI string. The service returns HTTP 202 ACCEPTED to the client when the response message relay was successful.<p> For example: <div class="fragment"><pre>soap_register_plugin(soap, soap_wsa); <span class="keywordflow">if</span> (<a class="code" href="wsaapi_8h.html#a9">soap_wsa_request</a>(soap, RequestMessageID, ToAddress, RequestAction) || <a class="code" href="wsaapi_8h.html#a10">soap_wsa_add_From</a>(soap, FromAddress) <span class="comment">// optional: add a 'From' address</span> || <a class="code" href="wsaapi_8h.html#a12">soap_wsa_add_ReplyTo</a>(soap, ReplyToAddress)) ... <span class="comment">// error: out of memory</span> <span class="keywordflow">if</span> (soap_call_ns__example(soap, ToAddress, NULL, ...)) { <span class="keywordflow">if</span> (soap->error == 202) <span class="comment">// HTTP ACCEPTED</span> printf(<span class="stringliteral">"Request was accepted and results were forwarded\n"</span>); <span class="keywordflow">else</span> soap_print_fault(soap, stderr); <span class="comment">// an error occurred</span> } <span class="keywordflow">else</span> <span class="comment">// unexpected OK: for some reason the response was not relayed</span> </pre></div><p> Note: the response message will be relayed when the From address is absent or different than the ReplyTo address<h3><a class="anchor" name="wsa_2_3"> Information Headers for Relaying Server Faults</a></h3> To relay a server fault message to another destination, the WS-Addressing FaultTo information header is added with <a class="el" href="wsaapi_8h.html#a13">soap_wsa_add_FaultTo()</a> by passing a relay address URI string. The service returns HTTP 202 ACCEPTED to the client when the fault was relayed.<p> For example: <div class="fragment"><pre>soap_register_plugin(soap, soap_wsa); <span class="keywordflow">if</span> (<a class="code" href="wsaapi_8h.html#a9">soap_wsa_request</a>(soap, RequestMessageID, ToAddress, RequestAction) || <a class="code" href="wsaapi_8h.html#a10">soap_wsa_add_From</a>(soap, FromAddress) <span class="comment">// optional: add a 'From' address</span> || <a class="code" href="wsaapi_8h.html#a13">soap_wsa_add_FaultTo</a>(soap, FaultToAddress)) ... <span class="comment">// error: out of memory</span> <span class="keywordflow">if</span> (soap_call_ns__example(soap, ToAddress, NULL, ...)) { <span class="keywordflow">if</span> (soap->error == 202) <span class="comment">// HTTP ACCEPTED</span> printf(<span class="stringliteral">"A fault occurred and the fault details were forwarded\n"</span>); <span class="keywordflow">else</span> soap_print_fault(soap, stderr); <span class="comment">// a connection error occurred</span> } <span class="keywordflow">else</span> <span class="comment">// process response </span> </pre></div><p> Note that the call can still return a fault, such as a connection error when the service is not responding. In addition to the fault relay, the responses can be relayed with <a class="el" href="wsaapi_8h.html#a12">soap_wsa_add_ReplyTo()</a>.<h3><a class="anchor" name="wsa_2_4"> Error Handling</a></h3> SOAP and HTTP errors set the soap->error attribute, as shown in this example: <div class="fragment"><pre><span class="keywordflow">if</span> (soap_call_ns__example(soap, ToAddress, NULL, ...)) { <span class="keywordflow">if</span> (soap->error == 202) <span class="comment">// HTTP ACCEPTED</span> printf(<span class="stringliteral">"A fault occurred and the fault details were forwarded\n"</span>); <span class="keywordflow">else</span> soap_print_fault(soap, stderr); <span class="comment">// a connection error occurred</span> } <span class="keywordflow">else</span> <span class="comment">// process response </span> </pre></div>When a WS-Addressing error occurred, the wsa error code is stored in the SOAP Fault Subcode field. This information can be retrieved with: <div class="fragment"><pre>wsa__FaultSubcodeValues fault; <span class="keywordflow">if</span> (<a class="code" href="wsaapi_8h.html#a20">soap_wsa_check_fault</a>(soap, &fault)) { <span class="keywordflow">switch</span> (fault) { <span class="keywordflow">case</span> wsa__InvalidMessageInformationHeader: ... <span class="keywordflow">case</span> wsa__MessageInformationHeaderRequired: ... <span class="keywordflow">case</span> wsa__DestinationUreachable: ... <span class="keywordflow">case</span> wsa__ActionNotSupported: ... <span class="keywordflow">case</span> wsa__EndpointUnavailable: ... } } </pre></div>When using wsa5.h, please refer to the standards and fault codes for this implementation. For the wsa5.h 2005/03 standard, several faults have an additional parameter (SOAP Fault detail): <div class="fragment"><pre>wsa5__FaultCodesType fault; <span class="keywordtype">char</span> *info; <span class="keywordflow">if</span> (<a class="code" href="wsaapi_8h.html#a20">soap_wsa_check_fault</a>(soap, &fault, &info)) { <span class="keywordflow">switch</span> (fault) { <span class="keywordflow">case</span> wsa5__InvalidAddressingHeader: <span class="keywordflow">if</span> (info) printf(<span class="stringliteral">"The invalid addressing header element is %s\n"</span>, info); ... } } </pre></div><h2><a class="anchor" name="wsa_3"> Server-side Usage</a></h2> The wsa plugin should be registered with: <div class="fragment"><pre>soap_register_plugin(soap, soap_wsa); </pre></div><p> Once the plugin is registered, the soap_bind(), soap_accept(), and soap_serve() functions can be called to process requests.<p> Important: to dispatch service operations based on the WS-Addressing wsa:Action information header, use soapcpp2 option -a. The generates a new dispatcher (in soapServer.c) based on the action value.<p> A service operation implementation should use <a class="el" href="wsaapi_8h.html#a14">soap_wsa_check()</a> to verify the validity of the WS-Addressing information headers in the SOAP request message. To allow response message to be automatically relayed based on the ReplyTo information header, the service operation should return <a class="el" href="wsaapi_8h.html#a15">soap_wsa_reply()</a> with an optional message UUID string and a mandatory response action string.<p> For example: <div class="fragment"><pre><span class="keywordtype">int</span> ns__example(<span class="keyword">struct</span> soap *soap, <span class="keywordtype">char</span> *in, <span class="keyword">struct</span> ns__exampleResponse *out) { <span class="keywordflow">if</span> (<a class="code" href="wsaapi_8h.html#a14">soap_wsa_check</a>(soap)) <span class="keywordflow">return</span> soap->error; <span class="comment">// ... service logic</span> <span class="keywordflow">return</span> <a class="code" href="wsaapi_8h.html#a15">soap_wsa_reply</a>(soap, ResponseMessageID, ResponseAction); } </pre></div><p> To return a SOAP fault that is automatically relayed to a fault service based on the FaultTo information header, the <a class="el" href="wsaapi_8h.html#a18">soap_wsa_sender_fault()</a>, <a class="el" href="wsaapi_8h.html#a19">soap_wsa_receiver_fault()</a>, <a class="el" href="wsaapi_8h.html#a16">soap_wsa_sender_fault_subcode()</a>, and <a class="el" href="wsaapi_8h.html#a17">soap_wsa_receiver_fault_subcode()</a> functions should be used instead of the soap_sender_fault(), soap_receiver_fault(), soap_sender_fault_subcode(), and soap_receiver_fault_subcode(), respectively.<p> For example: <div class="fragment"><pre><span class="keywordtype">int</span> ns__example(<span class="keyword">struct</span> soap *soap, <span class="keywordtype">char</span> *in, <span class="keyword">struct</span> ns__exampleResponse *out) { <span class="keywordflow">if</span> (<a class="code" href="wsaapi_8h.html#a14">soap_wsa_check</a>(soap)) <span class="keywordflow">return</span> soap->error; <span class="comment">// ... service logic</span> <span class="comment">// ... an error occurred, need to return fault possibly to fault service:</span> <span class="keywordflow">return</span> <a class="code" href="wsaapi_8h.html#a18">soap_wsa_sender_fault</a>(soap, <span class="stringliteral">"Exception in service operation"</span>, NULL); <span class="comment">// ... normal execution continues</span> <span class="keywordflow">return</span> <a class="code" href="wsaapi_8h.html#a15">soap_wsa_reply</a>(soap, ResponseMessageID, ResponseAction); } </pre></div><h2><a class="anchor" name="wsa_4"> Implementing a Server for Handling ReplyTo Response Messages</a></h2> To implement a separate server for handling relayed SOAP response messages based on the ReplyTo information header in the request message, the gSOAP header file should include a one-way service operation for the response message.<p> For example, suppose a service operation returns an exampleResponse message. We declare the one-way exampleResponse operation as follows: <div class="fragment"><pre><span class="preprocessor">#import "wsa.h"</span> <span class="comment">//gsoap ns service method-header-part: exampleResult wsa__MessageID</span> <span class="comment">//gsoap ns service method-header-part: exampleResult wsa__RelatesTo</span> <span class="comment">//gsoap ns service method-header-part: exampleResult wsa__From</span> <span class="comment">//gsoap ns service method-header-part: exampleResult wsa__ReplyTo</span> <span class="comment">//gsoap ns service method-header-part: exampleResult wsa__FaultTo</span> <span class="comment">//gsoap ns service method-header-part: exampleResult wsa__To</span> <span class="comment">//gsoap ns service method-header-part: exampleResult wsa__Action</span> <span class="comment">//gsoap ns service method-action: exampleResult urn:example/examplePort/exampleResponse</span> <span class="keywordtype">int</span> ns__exampleResponse(<span class="keywordtype">char</span> *out, <span class="keywordtype">void</span>); </pre></div><p> Note that the action information is important, because it is used by the service dispatcher (assuming soapcpp2 option -a is used).<p> The implementation in the server code uses <a class="el" href="wsaapi_8h.html#a14">soap_wsa_check()</a> to check the presense and validity of the WS-Addressing information header in the message. The soap_send_empty_response() function should be used to return an acknowledgment HTTP header with HTTP 202 ACCEPTED to the sender: <div class="fragment"><pre><span class="keywordtype">int</span> ns__exampleResponse(<span class="keyword">struct</span> soap *soap, <span class="keywordtype">char</span> *out) { <span class="keywordflow">if</span> (<a class="code" href="wsaapi_8h.html#a14">soap_wsa_check</a>(soap)) <span class="keywordflow">return</span> soap_send_empty_response(soap, 500); <span class="comment">// HTTP 500 Internal Server Error</span> <span class="comment">// ... service logic</span> <span class="keywordflow">return</span> soap_send_empty_response(soap, SOAP_OK); <span class="comment">// HTTP 202 ACCEPTED</span> } </pre></div><h2><a class="anchor" name="wsa_5"> Implementing a Server for Handling FaultTo Fault Messages</a></h2> To implement a separate server for handling relayed SOAP fault messages based on the FaultTo information header in the request message, the gSOAP header file for soapcpp2 should include a SOAP fault service operation. This operation accepts fault messages that are relayed by other services.<p> Basically, we use a trick to generate the SOAP-ENV:Fault struct via a one-way service operation. This allows us both to implement a one-way service operation that accepts faults and to automatically generate the fault struct for fault data storage and manipulation.<p> The fault operation in the header file should be declared as follows (for the 2004/08 standard): <div class="fragment"><pre><span class="comment">//gsoap SOAP_ENV service method-action: Fault http://schemas.xmlsoap.org/ws/2004/08/addressing/fault</span> <span class="keywordtype">int</span> SOAP_ENV__Fault ( _QName faultcode, <span class="comment">// SOAP 1.1</span> <span class="keywordtype">char</span> *faultstring, <span class="comment">// SOAP 1.1</span> <span class="keywordtype">char</span> *faultactor, <span class="comment">// SOAP 1.1</span> <span class="keyword">struct </span>SOAP_ENV__Detail *detail, <span class="comment">// SOAP 1.1</span> <span class="keyword">struct </span>SOAP_ENV__Code *SOAP_ENV__Code, <span class="comment">// SOAP 1.2</span> <span class="keyword">struct </span>SOAP_ENV__Reason *SOAP_ENV__Reason, <span class="comment">// SOAP 1.2</span> <span class="keywordtype">char</span> *SOAP_ENV__Node, <span class="comment">// SOAP 1.2</span> <span class="keywordtype">char</span> *SOAP_ENV__Role, <span class="comment">// SOAP 1.2</span> <span class="keyword">struct </span>SOAP_ENV__Detail *SOAP_ENV__Detail, <span class="comment">// SOAP 1.2</span> <span class="keywordtype">void</span> ); </pre></div><p> Because each service operation has a struct to hold its input parameters, we automatically generate the (original) SOAP_ENV__Fault struct on the fly!<p> Note: it is important to associate the wsa fault action with this operation as shown above.<p> The implementation of the service operation in the server code is: <div class="fragment"><pre><span class="keywordtype">int</span> SOAP_ENV__Fault(<span class="keyword">struct</span> soap *soap, <span class="keywordtype">char</span> *faultcode, <span class="keywordtype">char</span> *faultstring, <span class="keywordtype">char</span> *faultactor, <span class="keyword">struct</span> SOAP_ENV__Detail *detail, <span class="keyword">struct</span> SOAP_ENV__Code *SOAP_ENV__Code, <span class="keyword">struct</span> SOAP_ENV__Reason *SOAP_ENV__Reason, <span class="keywordtype">char</span> *SOAP_ENV__Node, <span class="keywordtype">char</span> *SOAP_ENV__Role, <span class="keyword">struct</span> SOAP_ENV__Detail *SOAP_ENV__Detail) { ... = faultcode; <span class="comment">// SOAP 1.1 fault code string (QName)</span> ... = faultstring; <span class="comment">// SOAP 1.1 fault string</span> ... = faultactor; <span class="comment">// SOAP 1.1 fault actor string</span> ... = detail; <span class="comment">// SOAP 1.1 fault detail struct</span> ... = SOAP_ENV__Code; <span class="comment">// SOAP 1.2 fault code struct</span> ... = SOAP_ENV__Reason; <span class="comment">// SOAP 1.2 reason struct</span> ... = SOAP_ENV__Node; <span class="comment">// SOAP 1.2 node string</span> ... = SOAP_ENV__Role; <span class="comment">// SOAP 1.2 role string</span> ... = SOAP_ENV__Detail; <span class="comment">// SOAP 1.2 detail struct</span> <span class="keywordflow">return</span> SOAP_OK; } </pre></div><p> Note that SOAP 1.1 or SOAP 1.2 parameters are set based on the 1.1/1.2 messaging requirements. <hr size="1"><address style="align: right;"><small>Generated on Fri Mar 19 13:59:43 2010 for gSOAP WS-Addressing by <a href="http://www.doxygen.org/index.html"> <img src="doxygen.png" alt="doxygen" align="middle" border=0 ></a> 1.3.8 </small></address> </body> </html>