See the section
notes from last Friday for help with the project. Also see the
sample
solutions for the midterm.
Today we'll look at SOAP, a simple but useful standard for building
web services. SOAP was defined in 1999, but the definition is still
evolving and it is not an official, stable standard yet. We'll discuss
a subset of SOAP 1.1. There are many implementations of it available,
but very few public services using it--we'll discuss possible reasons later.
SOAP uses HTTP because HTTP traffic is permitted by most firewalls. Note the paradox: because firewalls view other protocols as security risks, we are punching security holes into HTTP. However, security software can look at SOAP messages in HTTP and decide whether or not to accept them based on the the identity of the client and the server, and the name of the method being called. SOAP calls and responses can be encrypted using SSL, like web pages.
Despite its name, SOAP does not assume object-orientedness.
For this reason it is easy to use for small and simple servers, like sensor
devices, and server languages, like PHP.
Here is an example of a SOAP request:
POST /soapx4/soap.php HTTP/1.0The explanation below of this invocation is adapted mainly from A Busy Developer's Guide to SOAP 1.1 by Dave Winer and Jake Savin. Some explanations are also taken from http://www.xml.com/pub/a/2000/02/09/feature/ and other web pages.
User-Agent: SOAPx4 v0.5
Host: dietrich.ganx4.com
Content-Type: text/xml
Content-Length: 559
SOAPAction: "urn:soapinterop"<?xml version="1.0"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:si="http://soapinterop.org/xsd"
xmlns:ns6="http://soapinterop.org/ilab"
xmlns:ns7="http://soapinterop.org"
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body>
<ns7:echoDate>
<inputDate>
</inputDate>
</ns7:echoDate>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
First, note the use of XML namespaces, which avoids confusion between names of XML elements defined by different sources.
The URI (uniform resource identifier) after POST is to help route the request within the server. A User-Agent and Host must be specified, and the Content-Type is always text/xml. If Content-Length is specified, it must be correct.
SOAPAction is also used to route the request to a handler on the server. The application determines how this header element is used. Microsoft implementations of SOAP place constraints on SOAPAction that make compatibility with other SOAP implementations difficult.
Redundancy is to allow the HTTP-based infrastructure (proxies, firewalls,
web server software) to process the call without parsing XML, while also
allowing the XML payload to stand independent of the surrounding HTTP message.
As procedure parameters, we need to transmit structured data such as arrays. These are represented in XML elements within the procedure call. Their names are significant, not their order. The rules describe an element-normal-form encoding style, in which all values and parts of values of an instance are encoded as child elements, not as attributes. Types are indicated explicitly using attributes.
Common scalar value types are supported by SOAP 1.1, for example
xsd:int xsd:boolean
xsd:string xsd:double
and also some less usual ones, for example
xsd:timeInstant
2001-03-27T00:00:01-08:00
SOAP-ENC:base64
eW91IGNhbid0IHJlYWQgdGhpcyE=
A parameter value can also be a struct, which is simply an XML element that contains sub-elements. The names of struct elements are significant, the order of the elements is not. Here's an example of a four-element array, where each component has a different type:
<param SOAP-ENC:arrayType="xsd:ur-type[4]" xsi:type="SOAP-ENC:Array">
<item xsi:type="xsd:int">12</item>
<item xsi:type="xsd:string">Egypt</item>
<item xsi:type="xsd:boolean">0</item>
<item xsi:type="xsd:int">-31</item>
</param>
If the array elements are of a single type, the value of the array element's
SOAP-ENC:arrayType specifies the type of the array's sub-elements,
for example, SOAP-ENC:arrayType="xsd:int[4]" means an array of
four xsd:int elements. For mixed-type arrays, write SOAP-ENC:arrayType="xsd:ur-type[4]"
Upon receiving the request, the server-side software is expected to execute some code. How this happens is outside the scope of the SOAP protocol.
Here is an example of a non-error response:
HTTP/1.1 200 OKUnless there's an error, return 200 OK. The body of the response is a single <SOAP-ENV:Envelope> element with one <SOAP-ENV:Body> element, which contains a single element with a name which must match the name of the procedure that was called, with the word "Response" appended. The actual value of the response is contained in the single optional sub-element of the wrapper, which must be like a valid parameter. If the wrapper has no sub-elements then the procedure did not return a value.
Connection: close
Content-Length: 499
Content-Type: text/xml; charset=utf-8
Date: Wed, 28 Mar 2001 05:05:04 GMT
Server: UserLand Frontier/7.0-WinNT<?xml version="1.0"?>
<SOAP-ENV:Envelope
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/1999/XMLSchema"
xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"><SOAP-ENV:Body>
<m:getStateNameResponse xmlns:m="http://www.soapware.org/">
<Result xsi:type="xsd:string">South Dakota</Result>
</m:getStateNameResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
HTTP/1.1 500 Internal Server Error
Date: Mon, 19 Nov 2001 06:03:35 GMT
Server: Apache/1.3.20 (Unix) PHP/4.0.6 mod_gzip/1.3.19.1a
X-Powered-By: PHP/4.0.6
Connection: Close
Content-Length: 795
Content-Type: text/xml; charset=UTF-8<?xml version="1.0"?>
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:si="http://soapinterop.org/xsd" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><SOAP-ENV:Body>
<SOAP-ENV:Fault>
<faultcode xsi:type="xsd:string">Client</faultcode>
<faultstring xsi:type="xsd:string">
soap request contained mismatching parameters of name inputDate had type string,
which did not match signature's type: timeInstant
</faultstring>
<faultactor xsi:type="xsd:string"></faultactor>
<faultdetail xsi:type="xsd:string"></faultdetail>
</SOAP-ENV:Fault>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
To implement a SOAP server, you need to write a PHP script with the right name so that when a client sends a POST request to your web server, this script is executed. The server script must then look at the POST commands sent by the client to figure out what the client wants.
If the client sends a Content-Type that the PHP runtime
does not recognize, then the POST data received from the client will
be available to your script in the variable $HTTP_RAW_POST_DATA.
Your script can then parse the XML sent by the client, etc.