SOAP request/response maps nicely in HTTP, but SOAP has been used with other protocols and, in particular, SMTP. We are also aware of FTP implementations of SOAP.
If you remember Listings 5 and 6, a SOAP request is sent with the POST order. The SOAP response is transmitted with the HTTP response.
HTTP requests and responses contain one or more headers (not to be confused with the SOAP header that appears in the XML document) and one payload. SOAP imposes the use of two headers: Content-Type and SOAPAction.
The Content-Type must be set to text/xml, which is expected because it is the regular type for XML documents. SOAPAction, however, is new. Early in the development of SOAP, it was foreseen that proxies and firewalls might handle RPC requests differently from regular Web browsing. The SOAPAction header was introduced to alert proxies and firewalls on which requests are SOAP requests. You might argue that they could recognize SOAP requests from the env:Envelope element but, for increased efficiency, it's best if proxies and firewalls work on the headers only.
The SOAPAction content is a URI that supposedly identifies the intent of the call. In practice, most SOAP implementations ignore SOAPAction. It was introduced primarily for proxies.
The server uses the HTTP response code to indicate errors. A 2xx code accepts the request, whereas a 500 code signals the server could not process the request (the response includes a fault).
As a final note on HTTP binding, what about HTTP extension? The HTTP protocol offers an extension mechanism that was originally intended for special orders such as RPC. How come SOAP does not use it? The earliest drafts of SOAP mandated the use of the extension mechanism but experience showed that few HTTP libraries were compatible with it. By the time SOAP 1.0 was published, the standard was no longer recommending HTTP extension. With SOAP 1.1 and SOAP 1.2, HTTP extension remains as an option that is largely not implemented or used.
The only official SOAP binding is for HTTP, but the SOAP 1.2 working draft has a section on "SOAP Transport Binding Framework." The framework lays down the rules to bind SOAP to non-HTTP protocols. In the meantime, many SOAP implementations offer an SMTP binding. Most are based on the ebXML Transport, Routing, and Packaging specification (see http://www.ebxml.org).
Because HTTP and SMTP headers are similar, an SMTP binding is easily derived from the HTTP binding. SOAP emails include the SOAPAction header; the Content-Type header is set to text/xml. The To and From are set according to the SMTP rules.
Obviously, SMTP does not support synchronous calls (where the client waits for a immediate response from the server). It works in asynchronous mode, wherein the client sends a request and forgets about it. If the server sends a response, it comes in a different message.
SOAP with Attachments
Some applications of SOAP require that more than just the envelope be sent. The SOAP with Attachments note (available from http://www.w3.org/TR/SOAP-attachments) proposes a solution to send several documents in a SOAP 1.1 request. At the time of writing, no equivalent exists for SOAP 1.2.
SOAP with Attachments is defined as a special binding that uses the multipart/related MIME encoding rather than text/xml. As the name implies, multipart/related breaks the content of the HTTP request into several parts. By convention, the first part contains the SOAP envelope and is of type text/xml.
Each part includes a few headers, such as the Content-Type and a document. The parts may contain more XML documents, images, text, or any other files. In practice, they are similar to email attachments. This solution is attractive because it leaves the SOAP intact. In fact, the SOAP document is not aware of the multipart binding.
Listing 14 is an ebXML SOAP request with attachment. The SOAP envelope contains the now familiar MessageHeader and a new Manifest. The manifest lists the attachments. Note the use of XLink links to point to parts. MIME defines the Content-ID and Content-Name header to attach identifiers or names to the parts.
Listing 14An ebXML Multipart Request
POST /soap/servlet/rpcrouter HTTP/1.0 Host: joker.psol.com Content-Type: multipart/related; boundary=MIME_boundary; type=text/xml; start="<email@example.com>" Content-Length: 1682 SOAPAction: "ebXML" --MIME_boundary Content-ID: <firstname.lastname@example.org> Content-Type: text/xml <?xml version="1.0" encoding="UTF-8"?> <env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:eb="http://www.ebxml.org/namespaces/messageHeader"> <env:Header xmlns:eb="http://www.ebxml.org/namespaces/messageHeader"> <eb:MessageHeader env:mustUnderstand="1" eb:version="1.0"> <eb:From><eb:PartyId>urn:duns:374950798</eb:PartyId></eb:From> <eb:To><eb:PartyId>urn:duns:912345678</eb:PartyId></eb:To> <eb:CPAId>http://www.psol.com/cpas/default.xml</eb:CPAId> <eb:ConversationId>20011115-122303-28572</eb:ConversationId> <eb:Service>urn:services:SupplierOrderProcessing</eb:Service> <eb:Action>NewOrder</eb:Action> <eb:MessageData> <eb:MessageId>email@example.com</eb:MessageId> <eb:Timestamp>2001-11-15T11:12:12Z</eb:Timestamp> </eb:MessageData> </eb:MessageHeader> </env:Header> <env:Body> <eb:Manifest env:mustUnderstand="1" eb:version="1.0"> <eb:Reference xlink:href="cid:firstname.lastname@example.org" xlink:role="XLinkRole" xlink:type="simple" xmlns:xlink="http://www.w3.org/1999/xlink"> </eb:Reference> </eb:Manifest> </env:Body> </env:Envelope> --MIME_boundary Content-ID: <email@example.com> Content-Type: text/xml <?xml version="1.0"?> <Order xmlns="http://www.psol.com/2001/order"> <Reference>53</Reference> <ISBN>0-7897-2504-5</ISBN> <Title>XML by Example, Second Edition</Title> </Order> --MIME_boundary--
Note that according to the rules for MIME encoding, a boundary string separates the parts. The boundary string is defined in the boundary property (boundary=MIME_boundary, as shown in Listing 14).