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 Code
POST /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 Code
HTTP/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 Code
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)

其中,url 是 Web Service 的地址,headers 指定了消息的 Content-Type,data 是 SOAP 消息的 Envelope 和 Body 部分。

使用以上代码可以得到一个 SOAP HTTP Binding 响应。我们可以将响应的 Body 部分解析出来,获得上海的天气信息。

完整的代码如下:

pythonCopy Code
import 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 Code
Shanghai: temperature=28, humidity=80%

至此,我们成功使用 SOAP HTTP Binding 查询了上海的天气信息。