SOAP, WSDL and legacy web services
The envelope and header structure, how a WSDL describes a contract, SOAP faults, the 1.1 versus 1.2 differences, and when a SOAP integration is still the right answer.
The envelope is the whole protocol
<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope"
xmlns:shop="urn:example:shop">
<soap:Header>
<shop:AuthToken soap:mustUnderstand="true">abc123</shop:AuthToken>
</soap:Header>
<soap:Body>
<shop:GetOrder>
<shop:orderId>1024</shop:orderId>
</shop:GetOrder>
</soap:Body>
</soap:Envelope><soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
<soap:Body>
<soap:Fault>
<soap:Code>
<soap:Value>soap:Sender</soap:Value>
<soap:Subcode><soap:Value>shop:OrderNotFound</soap:Value></soap:Subcode>
</soap:Code>
<soap:Reason><soap:Text xml:lang="en">No such order.</soap:Text></soap:Reason>
<soap:Detail>
<shop:orderId xmlns:shop="urn:example:shop">1024</shop:orderId>
</soap:Detail>
</soap:Fault>
</soap:Body>
</soap:Envelope>- The header carries cross-cutting concerns: authentication, correlation, transaction and routing hints.
mustUnderstand="true"means the receiver must process that header or fail; ignoring it is a protocol violation.- A SOAP fault is a structured error inside a successful HTTP 500, which is why naive HTTP status handling misses it.
- SOAP 1.1 uses a different namespace and an
faultcodeandfaultstringshape; the two are not interchangeable.
Reading a WSDL
| WSDL element | Describes | Maps to |
|---|---|---|
types | The XSD schemas used in messages | Data model |
message | A named set of parts | Request or response payload |
portType | Abstract operations | The interface (WSDL 2.0 calls it interface) |
binding | Concrete protocol and style | SOAP 1.1 or 1.2 over HTTP |
service | Endpoints with addresses | The URL you call |
document versus rpc | Message style | Document is the interoperable choice |
literal versus encoded | Body encoding | Literal is the interoperable choice |
# inspect a WSDL and see the available operations
curl -s "https://service.example.com/OrderService?wsdl" | xmllint --format - | head -60
# call an operation by hand to see the real wire format
curl -s -X POST https://service.example.com/OrderService \
-H 'Content-Type: application/soap+xml; charset=utf-8' \
-H 'SOAPAction: "urn:example:shop/GetOrder"' \
--data-binary @request.xml | xmllint --format -The interoperable combination is document and literal. The rpc and encoded styles exist for historical reasons and are a common cause of mismatched expectations between toolkits.
When SOAP is still the right answer
- WS-Security provides message-level signing and encryption that survives intermediaries, which plain HTTPS does not.
- WS-ReliableMessaging and distributed transactions are specified and implemented, unlike their REST equivalents.
- Enterprise and government integrations often mandate a WSDL contract and an XSD-validated payload.
- A machine-readable contract and code generation are genuinely useful when both sides are large organisations that deploy slowly.
- For a new public API with simple resource semantics, the overhead of the envelope, the contract and the tooling is usually not repaid.
POST /OrderService HTTP/1.1
Content-Type: application/soap+xml; charset=utf-8; action="urn:example:shop/GetOrder"
SOAPAction: "urn:example:shop/GetOrder"
<!-- 1.1 puts the action in the SOAPAction header with quotes;
1.2 puts it in the content type parameter.
Sending the wrong one is a frequent interoperability failure. -->⚠️
Check the HTTP status and the SOAP fault, not one or the other. A service may return HTTP 200 with a fault in the body, or HTTP 500 with no useful body at all, and a client that trusts only the status code will treat a failure as success.
FAQ
Is SOAP dead?
No. It is absent from new consumer APIs and very much alive in enterprise, finance and government integrations where the WS- specifications solve a real problem.
Why do SOAP clients break when the server upgrades?
Usually a schema change in the WSDL types, or a new required header. Version the contract and keep the old endpoint available during the transition.
Related
XML Schema in practice: reuse and evolution XML security: XXE and entity expansion
Last refreshed 2026-09-18.