Web Service Backend Tutorial
Introduction
The objective of this tutorial is to provide to the user a simple guideline to create a basic Web Service with Apache, Perl and MySql on a Windows platform.
Web Services is a technology that involves several standards such as WSDL, XML Schema, SOAP, among others. The purpose of this document is not to give a deep explanation about all technologies used, but rather a general overview of the integration of those technologies.
After the completion of this tutorial the reader should be able to run an Api service locally in her/his computer.
Standards
As stated earlier, there are several standards which Web Services make use of. The following list gives a general description about the main standards that the Api Service uses. (For a more complete explanation see the "Reference" section in the appendix)
- WSDL (Web Service Description Language): a standard used to describe the services, operations and messages exposed by a Web Service.
- XML Schema: a standard used to describe rules to format XML documents.
- SOAP (Simple Object Access Protocol): a protocol for exchanging XML-based messages over computer networks.
Software
This service was developed on the Windows platform, but remarks about porting to Linux/Unix are
specified in section 7.1.
The following software is required to run the service:
- Apache: web server
- MySql: database server
- Perl: provide business logic
Configuration
Apache
In order to run the perl scripts the CGI module needs to be active. A line like the following
should be included in the "httpd.conf" configuration file:
LoadModule cgi_module modules/mod_cgi.so
Another module that will be required is alias which is used to map the "cgi-bin" directory:
LoadModule alias_module modules/mod_alias.so
The configuration should contain a section specifying the path to map the "cgi-bin" directory:
<IfModule alias_module>
ScriptAlias /cgi-bin/ "C:/my.bindows.distribution/samples/apiservice/"
</IfModule>
MySql
The service will require to connect to an existing "ApiService" database. It will also require to have
reading and writing permissions into the "classes" table. However, the database name, the user name and the
password can be configured in the "ApiService.pm" file as explained later.
The ApiService database template is found in the "ApiService.sql" file.
Perl
The Perl modules that will be required are:
- CGI: to provide the CGI functionality.
- SOAP::Transport::HTTP: to provide the transport of the SOAP messages.
- DBI: to provide the connections with the database.
Structure
Components
The files included in the ApiService application are listed below:
- ApiService.sql: a template for the ApiService database.
- ApiService.pl: a script to retrieve the WSDL file.
- ApiService.wsdl: the WSDL file of the ApiService.
- ApiServiceSoap.pl: a script to dispatch the SOAP messages to the appropriate operation.
- ApiServiceSoap.pm: a module to forward the parsed parameters to the ApiService module.
- ApiService.pm: the main module that actually processes the requests.
- ApiClient.xml: the Bindows client application.
Description
Figure 1 gives an overview of the service components interactions.
First, the client application calls the "ApiService.pl" script to retrieve the WSDL file. "ApiService.pl" in turn just reads the WSDL file and sends it back to the client application. Second, the client application parses the WSDL file and is able to invoke the available services and operations exposed by the ApiService with the required format. The messages have a SOAP format, which makes the backend to understand them.
Thereafter, the client application invokes an operation by sending a SOAP message to "ApiServiceSoap.pl". This script is only used for receiving and parsing the SOAP message to convert it into a Perl structure that "ApiServiceSoap.pm" can handle.
"ApiServiceSoap.pm" could directly process the request, but since this script is accessed without any restriction, the user could send a valid SOAP message invoking inappropriate methods, such as connectToDatabase. Therefore, "ApiServiceSoap.pm" forwards the message to "ApiService.pm" which has private and public methods to process the request.
Finally, the message arrives to "ApiService.pm" which interacts with the database performing the operation that the user wants.

Figure 1: Api Service structure
It is worth noting that the file "ApiService.wsdl" could be located anywhere, not necessarily in the same directory as the scripts. However, in this tutorial we kept the files together for the sake of clarity. If the WSDL file is located somewhere else, then the script "ApiService.pl" could be removed.
Functionality
Operations
The following operations have been implemented in the ApiService:
- getClasses: returns the available classes in the API.
- getClass: gets the description of a class.
- addClass: adds a class to the API.
Analysis
In order for the Web Service to work correctly it is necessary to have synchronization between the WSDL description and the operations in the Perl scripts. For example, analyzing the WSDL description of the getClasses operation:
<wsdl:operation name="getClasses"> <wsdl:documentation> ... </wsdl:documentation> <wsdl:input name="getClasses" message="tns:getClasses"/> <wsdl:output name="getClassesResponse" message="tns:getClassesResponse"/> </wsdl:operation>We see that the operation requires as input a message type getClasses and that it returns as output a message type getClassesResponse which are defined as <wsdl:message> sections:
<wsdl:message name="getClasses"> <wsdl:part name="parameters" type="tns:getClasses"/> </wsdl:message> <wsdl:message name="getClassesResponse"> <wsdl:part name="return" type="tns:getClassesResponse"/> </wsdl:message>Each of these messages in turn have a type which is defined in the <wsdl:types> section in a schema:
<xsd:complexType name="getClasses"> <xsd:sequence> <xsd:element minOccurs="0" maxOccurs="1" name="nMaxClasses" type="xsd:integer"/> </xsd:sequence> </xsd:complexType> <xsd:complexType name="getClassesResponse"> <xsd:all> <xsd:element minOccurs="1" maxOccurs="1" name="nStatus" type="xsd:integer"/> <xsd:element minOccurs="0" maxOccurs="1" name="nClasses" type="xsd:integer"/> <xsd:element minOccurs="0" maxOccurs="1" name="sClasses" type="xsd:string"/> </xsd:all> </xsd:complexType>We can notice that the type getClasses is composed by a sequence element with one child element: nMaxClasses. Furthermore, we can see that this element is optional, as minOccurs is an integer type that is equal to 0. These features of nMaxClasses are synchronized with the "ApiService.pm" script at:
# if we received a nMaxClasses parameter use it
# to limit the number of rows retrieved
$sQuery .= " LIMIT $rhParams->{ nMaxClasses }"
if( $rhParams->{ nMaxClasses } );
Where we can see that if the parameter nMaxClasses exist then the $sQuery string will append a
LIMIT restriction.
Similarly, we can see that for the type getClassesResponse we have an all element with
three children elements: nStatus, nClasses and sClasses, where the last two elements are
optional. In the perl script we can match these features at:
# return result object
return {nStatus => 1, nClasses => $nClasses, sClasses => "$sClasses"};
}
else
{
# we couldn't connect to the database, return an error
return {nStatus => 0};
}
Where the elements nClasses and sClasses are absent in case of an error.
Customizing
Porting to Unix/Linux
The ApiService can be ported to Unix/Linux with the following considerations:
- File permissions: the "*.pl" files should have execution permission for the httpd daemon.
- Shebang line: the first line of the "*.pl" files should be adjust to the right path of the perl binary
- File format: the format of the files should be changed from DOS to Unix
Deploying
If the service needs to be deployed then the targetNamespace in the WSDL file should be changed from localhost to my.domain.com, as well as all other occurrences of the word localhost.
Changing Complex Types from "All" to "Sequence"
Changing the element from all to sequence requires that the object return by the operation has the children elements ordered, this could be done through the package Tie::IxHash as in the following example:
use Tie::IxHash; ... tie my %hRes, 'Tie::IxHash', nStatus => $nStatus, nClasses => $nClasses, sClasses => $sClasses; return \%hRes;More information could be found at: Tie::IxHash.
Database account
If the user needs to change the database name, the user account or the password to access the database, the changes need to be done in the file "ApiService.pm" at:
our $rhSettings =
{
database => 'ApiService',
user => 'NewApiServiceUser',
pass => 'NewApiServicePass'
};
Limitations
This application has some security limitations, handling all of them is out of the scope of this document but the most common are mentioned in the following list:
- The scripts "*.pl" should run in tainted mode (perl -T) since is not possible to trust the information coming from the users. There is a high risk that the users actually insert SQL code in the requests making it possible to hack the system.
- The perl module "ApiService.pm" should use a library like SQL::Abstract which can check that the parameters inserted in the SQL queries are valid
Further development
The user of this tutorial should be able to experiment and add more operations as well as the necessary messages and types for them.
Some useful Perl libraries worth checking are JSON are XML::Parser.
Appendix
Reference
Web Service
WSDL
WSDL binding style/use
Schema