<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <meta http-equiv="Content-Type" content="text/html;charset=utf-8"> <meta http-equiv="cache-control" content="no-cache"> <title>Genivia - The Apache module for gSOAP</title> <link href="genivia_tabs.css" rel="stylesheet" type="text/css"/> <script type="text/javascript" src="jquery.js"></script> <script type="text/javascript" src="dynsections.js"></script> <link href="doxygen.css" rel="stylesheet" type="text/css"> <link href="genivia_content.css" rel="stylesheet" type="text/css"> </head> <body> <div id="top"> <div id="titlearea"> <table height="72px" width="100%" cellspacing="0" cellpadding="0"> <tbody> <tr> <td width="10%"> </td> <td width="175px"><a href="http://www.genivia.com"><img alt="Genivia" src="GeniviaLogo2_trans_noslogan.png"/></a></td> <td class="tab_home"><a href="http://www.genivia.com">Home</a></td> <td class="tab_home"><a href="http://www.genivia.com/docs.html">Documentation</a></td> <td> <div style="float: right; font-size: 18px; font-weight: bold;">The Apache module for gSOAP</div> <br> <div style="float: right; font-size: 10px;">updated Mon Feb 22 2016</div> </td> <td width="10%"> </td> </tr> </tbody> </table> </div> <!-- Generated by Doxygen 1.8.10 --> <div id="navrow1" class="tabs"> <ul class="tablist"> <li class="current"><a href="index.html"><span>Main Page</span></a></li> <li><a href="annotated.html"><span>Classes</span></a></li> <li><a href="files.html"><span>Files</span></a></li> </ul> </div> </div><!-- top --> <div class="header"> <div class="headertitle"> <div class="title">The Apache module for gSOAP </div> </div> </div><!--header--> <div class="contents"> <div class="toc"><h3>Table of Contents</h3> <ul><li class="level1"><a href="#overview">Overview </a></li> <li class="level1"><a href="#install">Installation </a></li> <li class="level1"><a href="#deploy">Deploying C services with the Apache module </a></li> <li class="level1"><a href="#libraries">Dynamic libraries </a></li> <li class="level1"><a href="#classes">Building C++ services from service classes </a></li> <li class="level1"><a href="#debug">Troubleshooting </a></li> <li class="level1"><a href="#license">License </a></li> <li class="level1"><a href="#references">Further reading </a></li> </ul> </div> <div class="textblock"><p>By Christian Aberger, Mick Wall, Robert van Engelen, David Viner, Ryan Troll, and La Cam Chung.</p> <h1><a class="anchor" id="overview"></a> Overview </h1> <p>SOAP/XML and REST Web services can be easily created and deployed as gSOAP standalone services or installed as (Fast)CGI applications. In addition, the <code>mod_gsoap</code> Apache module offers the ability to run gSOAP services directly inside the Apache HTTP server. The <code>mod_gsoap</code> Apache module supports the deployment of multiple gSOAP services that can run together with the usual services on Apache. This approach offers a production-quality Web services deployment scenario.</p> <p>The <code>mod_gsoap</code> Apache module is designed to keep things simple so that existing gSOAP services can be recompiled for Apache HTTP server deployment without modification of the source code. The Apache <code>apxs</code> command compiles your gSOAP service code and installs it with <code>mod_gsoap</code>. Add your new service to Apache <code>httpd.conf</code> and presto!</p> <p>The original Apache module for gSOAP home page is at <a href="http://mod-gsoap.sourceforge.net">http://mod-gsoap.sourceforge.net</a>.</p> <p>Apache modules for gSOAP are provided for both Apache 1.3 and 2.x. In the following we will discuss the Apache module for Apache 2.x.</p> <h1><a class="anchor" id="install"></a> Installation </h1> <p>First download and install Apache <code>httpd</code> in a new directory, say <code>apachegsoap</code>: </p><pre class="fragment">mkdir apachegsoap cd apachegsoap tar -xjf httpd-2.4.16.tar.bz2 cd httpd-2.2.31 ./configure --prefix=`pwd`/.. --with-mpm=worker --enable-mods-shared=most make -j4 make install </pre><p>To use the Apache extension mechanism, your platform has to support the DSO feature and your Apache <code>httpd</code> binary has to be built with the <code>mod_so</code> module. The <code>apxs</code> tool automatically complains if this is not the case. You can check this yourself by manually running the <code>httpd -l</code> command (here installed in <code>apachegsoap/bin</code> with our local installation): </p><pre class="fragment">cd apachegsoap bin/httpd -l </pre><p>The module <code>mod_so</code> should be on the displayed list of modules.</p> <p>Next, we will build and install <code>mod_gsoap</code> for Apache 2.x and up. The source code files are located under <code>gsoap/mod_gsoap/mod_gsoap-0.9/apache_20</code> and include <code><a class="el" href="apache__gsoap_8h.html">apache_gsoap.h</a></code>, <code><a class="el" href="mod__gsoap_8c.html">mod_gsoap.c</a></code>, and a Visual Studio project file <code>mod_gsoap.vcproj</code>.</p> <p>To compile <code>mod_gsoap</code>, execute: </p><pre class="fragment">cd /path/to/gsoap/installation/gsoap/mod_gsoap/mod_gsoap-0.9/apache_20 ln -s /path/to/gsoap/installation/gsoap/stdsoap2.h . sudo apxs -a -i -c mod_gsoap.c </pre><p>Root permissions are required, so we used <code>sudo apxs</code> here.</p> <p>The <code>apxs</code> command should be on your path or located in <code>apachegsoap/bin</code> (which is the case with our local installation).</p> <p>If a specific C compiler is required, say <code>cc</code>, then try <code>apxs -S CC=cc ...</code>.</p> <h1><a class="anchor" id="deploy"></a> Deploying C services with the Apache module </h1> <p>After building <code>mod_gsoap</code> we are ready to deploy gSOAP services written in C with the Apache module.</p> <p>The gSOAP package contains a calculator example. We will use this example to walk you through the creation and deployment of an Apache module gSOAP service.</p> <p>First, copy the calculator example: </p><pre class="fragment">cd apachegsoap cp /path/to/gsoap/installation/gsoap/samples/calc/* . cp /path/to/gsoap/installation/gsoap/stdsoap2.* . </pre><p>Next, edit <code>calcserver.c</code> by removing <code>main()</code> and replace it with <code><a class="el" href="apache__gsoap_8h.html#a044247a029c4997b5b22bba46d3ef233">IMPLEMENT_GSOAP_SERVER()</a></code> as follows:</p> <div class="fragment"><div class="line"><span class="preprocessor">#include "<a class="code" href="apache__gsoap_8h.html">apache_gsoap.h</a>"</span></div> <div class="line"><a class="code" href="apache__gsoap_8h.html#a044247a029c4997b5b22bba46d3ef233">IMPLEMENT_GSOAP_SERVER</a>() <span class="comment">/* replaces main() { ... } */</span></div> </div><!-- fragment --><p>Then compile and build the service: </p><pre class="fragment">soapcpp2 -c -SL -wx calc.h apxs -a -c calcserver.c soapC.c soapServer.c stdsoap2.c chmod 755 .libs/calcserver.so </pre><p>Again, the <code>apxs</code> command should be on your path or located in <code>apachegsoap/bin</code> (which is the case with our local installation).</p> <p>This creates <code>.libs/calcserver.so</code> service module that is universally readable. Also make sure that <code>.libs/calcserver.so</code> is readable through the entire path, that is through <code>/home/testuser/apachegsoap/.libs</code>.</p> <p>If you have installed source files in other directories, then you will need to add appropriate <code>-I</code> and <code>-L</code> options with the <code>apxs</code> command shown above.</p> <p>To deploy the service, we will need to add our module with its properties to <code>httpd.conf</code> (for example we can add it at the end): </p><pre class="fragment"><IfModule mod_gsoap.c> <Location /soap> SetHandler gsoap_handler SOAPLibrary /home/testuser/apachegsoap/.libs/calcserver.so Order allow,deny Allow from all </Location> </IfModule> </pre><p>The <code>httpd.conf</code> file is usually found under <code>/private/etc/apache2/httpd.conf</code>. However, since we use a locally installed Apache <code>httpd</code> server that searches the <code>/home/testuser/apachegsoap</code> path, you will find <code>httpd.conf</code> in <code>/home/testuser/apachegsoap/conf</code>.</p> <p>The <code>Location</code> property sets part of the URL of the service, which in this case will be <code><a href="http://localhost/soap">http://localhost/soap</a></code> or if you set a port that is different than the standard HTTP port 80, say 9080, the full URL is <code><a href="http://localhost:9080/soap">http://localhost:9080/soap</a></code>. To change the port from 80 to 9080, edit <code>httpd.conf</code> and change <code>Listen</code>: </p><pre class="fragment">Listen 9080 </pre><p>To start the service: </p><pre class="fragment">cd apachegsoap bin/apacectl start </pre><p>Point your browser to <code><a href="http://localhost:9080">http://localhost:9080</a></code> and the page should show the message "It works!".</p> <p>To stop the server: </p><pre class="fragment">bin/apacectl stop </pre><p>To use the service by client applications, direct the endpoint URL of clients to "http://localhost:9080/soap", for example in the <code>calcclient.c</code> code that came with the gSOAP example:</p> <div class="fragment"><div class="line"><span class="keyword">const</span> <span class="keywordtype">char</span> server[] = <span class="stringliteral">"http://localhost:9080/soap"</span>;</div> </div><!-- fragment --><p>Then we build the client: </p><pre class="fragment">soapcpp2 -c -CL -wx calc.h cc -o calcclient calcclient.c soapC.c soapClient.c stdsoap2.c </pre><p>and run it: </p><pre class="fragment">./calcclient add 2 3 result = 5 </pre><p>To let clients access the WSDL of a service, you can use the query <code>?wsdl</code> as part of the URL such as <code><a href="http://localhost:9080/soap?wsdl">http://localhost:9080/soap?wsdl</a></code> to pull the file <code>calc.wsdl</code> from the current location of the service. To do so, copy the <code>calc.wsdl</code> file there to make it available to the Apache server.</p> <h1><a class="anchor" id="libraries"></a> Dynamic libraries </h1> <p>If you are using dynamic libraries to deploy services with <code>mod_gsoap</code>, then those should be closed propertly to avoid memory leaks. To do so add:</p> <div class="fragment"><div class="line">dlclose(pConfig->m_pLibraries->m_pSOAPLibrary->m_hLibrary);</div> </div><!-- fragment --><p>at the end of the <code><a class="el" href="mod__gsoap_8c.html#a169e2de583e9017593f873dcf1f2173b">gsoap_handler()</a></code> function in <code><a class="el" href="mod__gsoap_8c.html">mod_gsoap.c</a></code>.</p> <h1><a class="anchor" id="classes"></a> Building C++ services from service classes </h1> <p>The Apache server is written in C. Building Apache modules in C++ is tricky and cannot be fully guaranteed due to compiler differences. Several online resources exist that can help to implement C++ modules for Apache 2.0. If this fails, the best alternative is to use FastCGI (see gSOAP user guide on "FastCGI Support").</p> <p>When using C++ gSOAP service classes generated by <code>soapcpp2</code> options <code>-i</code> or <code>-j</code> we need to implement the C function <code>soap_serve()</code> that dispatches the services.</p> <p>We will walk through the implementation of a service using the same calculator example demonstrated above.</p> <p>First, run <code>soapcpp2</code> with option <code>-j</code> to generate a service class: </p><pre class="fragment">soapcpp2 -j -SL -wx calc.h </pre><p>Create a new <code>calcerver.cpp</code> file with the following code:</p> <div class="fragment"><div class="line"><span class="preprocessor">#include "soapcalcService.h"</span></div> <div class="line"><span class="preprocessor">#include "calc.nsmap"</span></div> <div class="line"><span class="preprocessor">#include "<a class="code" href="apache__gsoap_8h.html">apache_gsoap.h</a>"</span></div> <div class="line"><a class="code" href="apache__gsoap_8h.html#a044247a029c4997b5b22bba46d3ef233">IMPLEMENT_GSOAP_SERVER</a>()</div> <div class="line">extern "C" <span class="keywordtype">int</span> soap_serve(struct soap *soap)</div> <div class="line">{</div> <div class="line"> calcService service(soap);</div> <div class="line"> <span class="keywordtype">int</span> err = service.serve();</div> <div class="line"> service.destroy();</div> <div class="line"> <span class="keywordflow">return</span> err;</div> <div class="line">}</div> <div class="line"><span class="keywordtype">int</span> calcService::add(<span class="keywordtype">double</span> a, <span class="keywordtype">double</span> b, <span class="keywordtype">double</span> *result)</div> <div class="line">{</div> <div class="line"> *result = a + b;</div> <div class="line"> <span class="keywordflow">return</span> SOAP_OK;</div> <div class="line">} </div> <div class="line"><span class="keywordtype">int</span> calcService::sub(<span class="keywordtype">double</span> a, <span class="keywordtype">double</span> b, <span class="keywordtype">double</span> *result)</div> <div class="line">{</div> <div class="line"> *result = a - b;</div> <div class="line"> <span class="keywordflow">return</span> SOAP_OK;</div> <div class="line">} </div> <div class="line"><span class="keywordtype">int</span> calcService::mul(<span class="keywordtype">double</span> a, <span class="keywordtype">double</span> b, <span class="keywordtype">double</span> *result)</div> <div class="line">{</div> <div class="line"> *result = a * b;</div> <div class="line"> <span class="keywordflow">return</span> SOAP_OK;</div> <div class="line">} </div> <div class="line"><span class="keywordtype">int</span> calcService::div(<span class="keywordtype">double</span> a, <span class="keywordtype">double</span> b, <span class="keywordtype">double</span> *result)</div> <div class="line">{</div> <div class="line"> *result = b != 0 ? a / b : 0.0;</div> <div class="line"> <span class="keywordflow">return</span> SOAP_OK;</div> <div class="line">} </div> <div class="line"><span class="keywordtype">int</span> calcService::pow(<span class="keywordtype">double</span> a, <span class="keywordtype">double</span> b, <span class="keywordtype">double</span> *result)</div> <div class="line">{</div> <div class="line"> *result = ::pow(a, b);</div> <div class="line"> <span class="keywordflow">return</span> SOAP_OK;</div> <div class="line">}</div> </div><!-- fragment --><p>Here, <code>calcService</code> is the service class defined in the generated <code>soapcalcService.h</code> and <code>soapcalcService.cpp</code> files.</p> <p>The <code>apxs</code> command is used to compile as follows, with the <code>-S CC=c++</code> option: </p><pre class="fragment">apxs -a -c -S CC=c++ calcserver.cpp soapC.cpp soapcalcService.cpp stdsoap2.cpp chmod 755 .lib/calcserver.so </pre><p>This creates <code>.libs/calcserver.so</code> service module that is universally readable. Also make sure that <code>.libs/calcserver.so</code> is readable through the entire path, that is through <code>/home/testuser/apachegsoap/.libs</code>.</p> <p>The module should also be added to <code>httpd.conf</code>, as was explained above.</p> <p>When multiple service classes are defined, when <code>soapcpp2 -j</code> is applied to multiple <code>.h</code> files, then you have two options:</p> <ol type="1"> <li>create an <code>.so</code> library for each service and add each module to <code>httpd.conf</code> with a new <code>Location</code> property.</li> <li>create one <code>.so</code> library with the services combined, all listening to the same service URL. Only one module is added to <code>httpd.conf</code> since the <code>Location</code> property is the same. Note that the <code>?wsdl</code> query is not as useful in this case, since we cannot publicize the service WSDLs combined.</li> </ol> <p>The second option requires C++ namespaces as explained in section "How to Chain C++ Server Classes to Accept Messages on the Same Port" in the gSOAP user guide. Basically, you should chain the services as follows:</p> <div class="fragment"><div class="line"><span class="preprocessor">#include "<a class="code" href="apache__gsoap_8h.html">apache_gsoap.h</a>"</span></div> <div class="line"><a class="code" href="apache__gsoap_8h.html#a044247a029c4997b5b22bba46d3ef233">IMPLEMENT_GSOAP_SERVER</a>()</div> <div class="line">extern "C" <span class="keywordtype">int</span> soap_serve(struct soap *soap)</div> <div class="line">{</div> <div class="line"> <span class="keywordtype">int</span> err;</div> <div class="line"> <span class="keywordflow">if</span> ((err = soap_begin_serve(soap)) == SOAP_OK)</div> <div class="line"> {</div> <div class="line"> X::Service service_x(soap);</div> <div class="line"> <span class="keywordflow">if</span> ((err = service_x.dispatch()) == SOAP_NO_METHOD)</div> <div class="line"> {</div> <div class="line"> Y::Service service_y(soap);</div> <div class="line"> <span class="keywordflow">if</span> ((err = service_y.dispatch()) == SOAP_NO_METHOD)</div> <div class="line"> {</div> <div class="line"> Z::Service service_z(soap);</div> <div class="line"> err = service_z.dispatch();</div> <div class="line"> }</div> <div class="line"> }</div> <div class="line"> } </div> <div class="line"> soap_destroy(soap);</div> <div class="line"> soap_end(soap);</div> <div class="line"> <span class="keywordflow">return</span> err;</div> <div class="line">}</div> </div><!-- fragment --><h1><a class="anchor" id="debug"></a> Troubleshooting </h1> <p>It is recommended to test the service first as a stand-alone server over a port using <code>soap_bind()</code> and <code>soap_accept()</code>. Debugging as much easier this way.</p> <p>In case you need to debug the service as it is deployed while is <code>httpd</code> running, we first stop the service and start it up in single threaded mode so we can attach to it to a debugger such as <code>gdb</code> or <code>lldb</code>. </p><pre class="fragment">cd apachegsoap bin/apacectl stop bin/httpd -X -f /home/testuser/apachegsoap/conf/httpd.conf & </pre><p>You will get a process ID, say 12345, which we will attach to a debugger: </p><pre class="fragment">gdb /home/testuser/apachegsoap/bin/httpd 12345 </pre><p>You will see a load of symbols loading, including <code>mod_gsoap.so</code>.</p> <p>Next, we set a breakpoint on the <code>soap_serve</code> call (the main entry point), let <code>gdb</code> know that we accept the pending breakpoint, and then continue the process: </p><pre class="fragment">(gdb) b soap_serve Function "soap_serve" not defined. Make breakpoint pending on future shared library load? (y or [n]) y Breakpoint 1 (soap_serve) pending. (gdb) c Continuing. </pre><p>We execute our <code>calcclient</code> from another window, which triggers the breakpoint. </p><pre class="fragment">[Switching to Thread 0x7f3fbd209950 (LWP 25493)] Breakpoint 1, 0x00007f3fb059e398 in soap_serve () from /home/testuser/apachegsoap/gsoap-2.8/gsoap/samples/calc/.libs/calcserver.so Current language: auto; currently asm (gdb) n Single stepping until exit from function soap_serve, which has no line number information. 0x00007f3fb05a5eec in apache_default_soap_serve () from /home/testuser/apachegsoap/gsoap-2.8/gsoap/samples/calc/.libs/calcserver.so (gdb) </pre><p>Note that when Apache <code>httpd</code> runs as user <code>wwwrun</code> (or another user) then you will have to run the debugger as that same user. To do so, execute: </p><pre class="fragment">sudo -u wwwrun gdb /usr/sbin/httpd2-worker 25487 </pre><p>Thanks to Jon Scobie for suggestions.</p> <h1><a class="anchor" id="license"></a> License </h1> <p>The Apache modules for gSOAP are released under the gSOAP open source public license (compatible with commercial licensing) and GPLv2.</p> <h1><a class="anchor" id="references"></a> Further reading </h1> <p><a href="http://techiebitsandpieces.blogspot.com/2011/03/all-things-modgsoap.html">All things `mod_gsoap`</a> by Jon Scobie</p> <p><a href="http://httpd.apache.org/download.cgi">Apache HTTP server project</a>. </p> </div></div><!-- contents --> <hr class="footer"> <address class="footer"> Copyright (C) 2016, Robert van Engelen, Genivia Inc., All Rights Reserved. </address> <address class="footer"><small> Converted on Mon Feb 22 2016 19:59:34 by <a target="_blank" href="http://www.doxygen.org/index.html">Doxygen</a> 1.8.10</small></address> <br> <div style="height: 246px; background: #DBDBDB;"> </body> </html>