SOAP fue desarrollado por un consorcio liderado por Microsoft, IBM y otros grandes actores de la industria en 1998. Se convirtió en un estándar del World Wide Web Consortium (W3C) en 2000. SOAP fue diseñado para superar las limitaciones de los métodos de comunicación existentes entre aplicaciones, proporcionando una forma más flexible y robusta de intercambiar datos.
El propósito principal de SOAP es facilitar la comunicación entre aplicaciones en una red, especialmente en entornos heterogéneos donde las aplicaciones pueden estar construidas en diferentes lenguajes de programación y ejecutarse en diferentes sistemas operativos. SOAP permite que estas aplicaciones se comuniquen mediante el intercambio de mensajes XML, que son independientes de la plataforma y del lenguaje.
SOAP se compone de varios elementos clave que trabajan juntos para permitir la comunicación entre aplicaciones. Estos componentes son:
1. Envoltorio (Envelope)
2. Encabezado (Header)
3. Cuerpo (Body)
4. Falta de Dependencia de Transporte
El envoltorio es el elemento raíz de un mensaje SOAP y define el marco general del mensaje. Indica que el mensaje es un mensaje SOAP y contiene el encabezado y el cuerpo del mensaje.
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
<soap:Header>
<!-- Encabezado -->
</soap:Header>
<soap:Body>
<!-- Cuerpo -->
</soap:Body>
</soap:Envelope>
El encabezado es opcional y puede contener información sobre cómo procesar el mensaje. Esta información puede incluir detalles de seguridad, transacciones, o enrutamiento. Cada elemento del encabezado se define en su propio espacio de nombres.
<soap:Header>
<wss:Security xmlns:wss="http://schemas.xmlsoap.org/ws/2002/12/secext">
<!-- Información de seguridad -->
</wss:Security>
</soap:Header>
El cuerpo contiene el mensaje principal que se está intercambiando entre el cliente y el servidor. Este es el elemento obligatorio del mensaje SOAP y contiene los datos reales de la solicitud o la respuesta.
<soap:Body>
<m:GetStockPrice xmlns:m="https://www.example.org/stock">
<m:StockName>IBM</m:StockName>
</m:GetStockPrice>
</soap:Body>
SOAP está diseñado para ser independiente del protocolo de transporte. Esto significa que puede utilizar diferentes protocolos de transporte, como HTTP, SMTP, TCP, etc. Sin embargo, HTTP es el protocolo de transporte más comúnmente utilizado con SOAP debido a su amplia aceptación y uso en la web.
Un mensaje SOAP típico tiene la siguiente estructura:
1. Declaración XML
2. Envoltorio (Envelope)
3. Encabezado (Header)
4. Cuerpo (Body)
5. Detalles de Error (Fault)
La declaración XML especifica que el documento es un documento XML y la versión de XML que se está utilizando.
<?xml version="1.0" encoding="UTF-8"?>
El elemento Envelope
es el contenedor del mensaje SOAP y define el espacio de nombres para los elementos SOAP.
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
El encabezado es opcional y puede contener elementos como información de autenticación y detalles de transacciones.
<soap:Header>
<!-- Elementos opcionales -->
</soap:Header>
El cuerpo contiene la información del mensaje que se envía o recibe. Puede incluir cualquier estructura de datos definida por el usuario.
<soap:Body>
<m:GetStockPrice xmlns:m="https://www.example.org/stock">
<m:StockName>IBM</m:StockName>
</m:GetStockPrice>
</soap:Body>
El elemento Fault
es opcional y se utiliza para proporcionar información sobre errores que ocurren durante el procesamiento del mensaje SOAP.
<soap:Body>
<soap:Fault>
<faultcode>soap:Client</faultcode>
<faultstring>Invalid request</faultstring>
<faultactor>https://www.example.org/someactor</faultactor>
<detail>
<errorcode>1001</errorcode>
<errormessage>Invalid StockName</errormessage>
</detail>
</soap:Fault>
</soap:Body>
Aunque SOAP es independiente del transporte, HTTP es el protocolo de transporte más comúnmente utilizado. A continuación, se muestra cómo se envían y reciben mensajes SOAP a través de HTTP.
Cuando se envía un mensaje SOAP a través de HTTP, el mensaje SOAP se incluye en el cuerpo de la solicitud HTTP. La cabecera Content-Type
se establece en application/soap+xml
.
POST /StockPrice HTTP/1.1
Host: www.example.org
Content-Type: application/soap+xml; charset=utf-8
Content-Length: nnn
<?xml version="1.0"?>
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
<soap:Header>
<!-- Encabezado -->
</soap:Header>
<soap:Body>
<m:GetStockPrice xmlns:m="https://www.example.org/stock">
<m:StockName>IBM</m:StockName>
</m:GetStockPrice>
</soap:Body>
</soap:Envelope>
La respuesta SOAP se incluye en el cuerpo de la respuesta HTTP. La cabecera Content-Type
también se establece en application/soap+xml
.
HTTP/1.1 200 OK
Content-Type: application/soap+xml; charset=utf-8
Content-Length: nnn
<?xml version="1.0"?>
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
<soap:Body>
<m:GetStockPriceResponse xmlns:m="https://www.example.org/stock">
<m:Price>34.5</m:Price>
</m:GetStockPriceResponse>
</soap:Body>
</soap:Envelope>
SOAP y REST (Representational State Transfer) son dos enfoques diferentes para construir servicios web. A continuación, se presentan algunas diferencias clave entre ambos.
El WSDL (Web Services Description Language) es un documento XML que describe los servicios web SOAP. Define las operaciones, los parámetros y los tipos de datos que se pueden utilizar.
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="https://www.example.org/stock"
targetNamespace="https://www.example.org/stock"
name="StockService">
<message name="GetStockPriceRequest">
<part name="StockName" type="xsd:string"/>
</message>
<message name="GetStockPriceResponse">
<part name="Price" type="xsd:float"/>
</message>
<portType name="StockPortType">
<operation name="GetStockPrice">
<input message="tns:GetStockPriceRequest"/>
<
output message="tns:GetStockPriceResponse"/>
</operation>
</portType>
<binding name="StockBinding" type="tns:StockPortType">
<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="GetStockPrice">
<soap:operation soapAction="GetStockPrice"/>
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
</operation>
</binding>
<service name="StockService">
<port name="StockPort" binding="tns:StockBinding">
<soap:address location="http://www.example.org/stockservice"/>
</port>
</service>
</definitions>
La implementación del servicio depende del lenguaje y el entorno de desarrollo que estés utilizando. A continuación, se muestra un ejemplo en Node.js utilizando la biblioteca soap
.
npm install soap
const soap = require('soap');
const express = require('express');
const bodyParser = require('body-parser');
const stockPrices = {
IBM: 34.5,
AAPL: 145.3,
GOOG: 2731.6
};
const service = {
StockService: {
StockPortType: {
GetStockPrice(args) {
return { Price: stockPrices[args.StockName] || 0.0 };
}
}
}
};
const wsdl = `<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="https://www.example.org/stock"
targetNamespace="https://www.example.org/stock"
name="StockService">
<message name="GetStockPriceRequest">
<part name="StockName" type="xsd:string"/>
</message>
<message name="GetStockPriceResponse">
<part name="Price" type="xsd:float"/>
</message>
<portType name="StockPortType">
<operation name="GetStockPrice">
<input message="tns:GetStockPriceRequest"/>
<output message="tns:GetStockPriceResponse"/>
</operation>
</portType>
<binding name="StockBinding" type="tns:StockPortType">
<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="GetStockPrice">
<soap:operation soapAction="GetStockPrice"/>
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
</operation>
</binding>
<service name="StockService">
<port name="StockPort" binding="tns:StockBinding">
<soap:address location="http://www.example.org/stockservice"/>
</port>
</service>
</definitions>`;
const app = express();
app.use(bodyParser.raw({ type: () => true, limit: '5mb' }));
app.listen(8000, () => {
console.log('SOAP service is running on http://localhost:8000');
soap.listen(app, '/stockservice', service, wsdl);
});
Para consumir un servicio SOAP, puedes utilizar una variedad de lenguajes y bibliotecas. A continuación, se muestra un ejemplo en Python utilizando la biblioteca zeep
.
pip install zeep
from zeep import Client
wsdl = 'http://localhost:8000/stockservice?wsdl'
client = Client(wsdl=wsdl)
response = client.service.GetStockPrice(StockName='IBM')
print(f'The price of IBM stock is {response.Price}')
SOAP es un protocolo poderoso y flexible para la comunicación entre aplicaciones en una red. Aunque ha sido en gran parte reemplazado por REST en muchas aplicaciones modernas debido a su simplicidad y menor carga de sobrecarga, SOAP sigue siendo relevante en entornos empresariales donde la seguridad, la transaccionalidad y la interoperabilidad son críticas.
Comprender cómo funciona SOAP, desde su estructura de mensajes hasta su transporte y uso práctico, es esencial para los desarrolladores que trabajan en sistemas de integración y servicios web complejos. Este conocimiento permite diseñar y mantener servicios robustos y seguros que pueden operar en diversos entornos y plataformas.
Jorge García
Fullstack developer