SOAP HTTP Binding 学习笔记
SOAP 简介
SOAP (Simple Object Access Protocol) 是一种基于 XML 的消息协议,用于在分布式环境中进行应用程序之间的通信。
SOAP 消息格式由以下部分组成:
- Envelope:包含整个消息的信息。
- Header:包含头部信息,比如身份验证等。
- Body:包含实际的消息内容。
- Fault:用于表示错误信息。
SOAP 消息可以使用不同的协议进行传输,比如 HTTP、SMTP 等。本文主要讨论基于 HTTP 的 SOAP 协议,即 SOAP HTTP Binding。
SOAP HTTP Binding
SOAP HTTP Binding 是一种将 SOAP 消息绑定到 HTTP 请求和响应上的方式,使得 SOAP 消息可以通过 HTTP 协议进行传输。
在 SOAP HTTP Binding 中,一个 SOAP 请求被打包成一个 HTTP POST 请求,并且 SOAP 响应被打包成一个 HTTP 响应。
HTTP POST 请求中的消息体为 SOAP 消息的 Envelope 和 Body 部分。而 HTTP 响应中的消息体则是 SOAP 消息的 Envelope、Header 和 Body 部分。
下面是一个示例 SOAP HTTP Binding 请求和响应:
请求
xmlCopy CodePOST /service HTTP/1.1
Host: example.com
Content-Type: text/xml; charset=utf-8
Content-Length: nnnn
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Header>
<authToken>token</authToken>
</soap:Header>
<soap:Body>
<getWeather>
<city>Shanghai</city>
</getWeather>
</soap:Body>
</soap:Envelope>
响应
xmlCopy CodeHTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: nnnn
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Header>
<serverDate>2023-06-05T04:48:05</serverDate>
</soap:Header>
<soap:Body>
<weather>
<city>Shanghai</city>
<temperature>28</temperature>
<humidity>80%</humidity>
</weather>
</soap:Body>
</soap:Envelope>
实例
假设我们有一个天气预报的 SOAP Web Service,可以根据城市名称查询该城市的天气信息。该 Web Service 的 WSDL 定义如下:
xmlCopy Code<?xml version="1.0"?>
<wsdl:definitions name="WeatherService"
targetNamespace="http://example.com/weatherservice"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="http://example.com/weatherservice/types">
<wsdl:message name="GetWeatherRequest">
<wsdl:part name="city" type="string"/>
</wsdl:message>
<wsdl:message name="GetWeatherResponse">
<wsdl:part name="weather" type="tns:Weather"/>
</wsdl:message>
<wsdl:portType name="WeatherServicePortType">
<wsdl:operation name="GetWeather">
<wsdl:input message="tns:GetWeatherRequest"/>
<wsdl:output message="tns:GetWeatherResponse"/>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="WeatherServiceSOAPBinding" type="tns:WeatherServicePortType">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="GetWeather">
<soap:operation soapAction="http://example.com/weatherservice/GetWeather"/>
<wsdl:input>
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output>
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="WeatherService">
<wsdl:port name="WeatherServiceSOAPPort" binding="tns:WeatherServiceSOAPBinding">
<soap:address location="http://example.com/weatherservice"/>
</wsdl:port>
</wsdl:service>
<wsdl:types>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://example.com/weatherservice/types">
<xsd:complexType name="Weather">
<xsd:sequence>
<xsd:element name="city" type="xsd:string"/>
<xsd:element name="temperature" type="xsd:int"/>
<xsd:element name="humidity" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
</wsdl:types>
</wsdl:definitions>
假设我们要查询上海的天气信息,我们可以使用以下代码生成一个 SOAP HTTP Binding 请求:
pythonCopy Codeimport requests
url = 'http://example.com/weatherservice'
headers = {'Content-Type': 'text/xml; charset=utf-8'}
data = '''<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Header>
<authToken>token</authToken>
</soap:Header>
<soap:Body>
<getWeather>
<city>Shanghai</city>
</getWeather>
</soap:Body>
</soap:Envelope>'''
response = requests.post(url, headers=headers, data=data)
其中,url
是 Web Service 的地址,headers
指定了消息的 Content-Type,data
是 SOAP 消息的 Envelope 和 Body 部分。
使用以上代码可以得到一个 SOAP HTTP Binding 响应。我们可以将响应的 Body 部分解析出来,获得上海的天气信息。
完整的代码如下:
pythonCopy Codeimport xml.etree.ElementTree as ET
import requests
url = 'http://example.com/weatherservice'
headers = {'Content-Type': 'text/xml; charset=utf-8'}
data = '''<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Header>
<authToken>token</authToken>
</soap:Header>
<soap:Body>
<getWeather>
<city>Shanghai</city>
</getWeather>
</soap:Body>
</soap:Envelope>'''
response = requests.post(url, headers=headers, data=data)
# 解析响应的 Body 部分
root = ET.fromstring(response.content)
ns = {'soap': 'http://schemas.xmlsoap.org/soap/envelope/',
'ns': 'http://example.com/weatherservice/types'}
city = root.find('.//ns:city', ns).text
temperature = root.find('.//ns:temperature', ns).text
humidity = root.find('.//ns:humidity', ns).text
print(f'{city}: temperature={temperature}, humidity={humidity}')
以上代码将打印出以下结果:
Copy CodeShanghai: temperature=28, humidity=80%
至此,我们成功使用 SOAP HTTP Binding 查询了上海的天气信息。