一个带 WSDL 的免费 SOAP 测试 API
一个带 WSDL 的计算器服务和一个国家服务,两者都以 SOAP 1.1 和 1.2 响应。
示例最后一次针对 API 运行于
想找一个公共 SOAP API 来测试客户端,可以用 https://api.testingapis.com/api/soap/calculator登录后查看。它的 WSDL 位于 https://api.testingapis.com/api/soap/calculator?wsdl登录后查看,SoapUI、Postman、WCF 和 Python 的 zeep 都能导入。它有四个操作:Add、Subtract、Multiply 和 Divide。它接受 SOAP 1.1 和 SOAP 1.2,并返回规范的 SOAP fault,所以既能测试结果,也能测试错误。 另一个服务 /api/soap/countries登录后查看 返回结构化的国家记录。两者都免费,无需注册,也不需要 API 密钥。
| 计算器 | 国家 | |
|---|---|---|
| 端点 | POST /api/soap/calculator登录后查看 | POST /api/soap/countries登录后查看 |
| WSDL | GET /api/soap/calculator?wsdl登录后查看 | 没有。对端点发 GET 可获得用法说明 JSON 和示例信封 |
| 命名空间 | http://tempuri.org/ | http://example.com/countries |
| 操作 | Add、Subtract、Multiply、Divide(整数) | GetCountryInfo(countryCode)、ListCountries() |
| 版本 | SOAP 1.1 和 1.2 | SOAP 1.1 和 1.2 |
用 curl 调用(SOAP 1.1)
SOAP 1.1 使用 Content-Type: text/xml,以及一个指明操作名的 SOAPAction 请求头。这里这个请求头是可选的,但如果发送,它必须与请求体中的操作一致。
curl -X POST https://api.testingapis.com/api/soap/calculator \
-H 'Content-Type: text/xml; charset=utf-8' \
-H 'SOAPAction: "http://tempuri.org/Add"' \
-d '<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<Add xmlns="http://tempuri.org/"><intA>5</intA><intB>3</intB></Add>
</soap:Body>
</soap:Envelope>'HTTP/1.1 200 OK
content-type: text/xml; charset=utf-8
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<AddResponse xmlns="http://tempuri.org/">
<AddResult>8</AddResult>
</AddResponse>
</soap:Body>
</soap:Envelope>SOAP 1.2 与 fault
SOAP 1.2 使用 Content-Type: application/soap+xml、不同的信封命名空间,并且没有 SOAPAction 请求头。响应使用与请求相同的版本。除以零会返回一个 Receiver fault:
curl -X POST https://api.testingapis.com/api/soap/calculator \
-H 'Content-Type: application/soap+xml; charset=utf-8' \
-d '<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
<soap:Body>
<Divide xmlns="http://tempuri.org/"><intA>10</intA><intB>0</intB></Divide>
</soap:Body>
</soap:Envelope>'HTTP/1.1 500 Internal Server Error
content-type: application/soap+xml; charset=utf-8
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
<soap:Body>
<soap:Fault>
<soap:Code>
<soap:Value>soap:Receiver</soap:Value>
</soap:Code>
<soap:Reason>
<soap:Text xml:lang="en">Attempted to divide by zero.</soap:Text>
</soap:Reason>
</soap:Fault>
</soap:Body>
</soap:Envelope>fault 的规则遵循规范,这正是客户端需要用来测试的依据:
| 情况 | SOAP 1.1 | SOAP 1.2 |
|---|---|---|
| 输入错误(未知的国家代码) | 500,faultcode soap:Client | 400,Code soap:Sender |
| 服务器端错误(除以零) | 500,faultcode soap:Server | 500,Code soap:Receiver |
| SOAPAction 指向另一个操作 | 500 fault | 不适用 |
| Content-Type 错误(如 JSON) | 带 JSON 错误的 415 | 带 JSON 错误的 415 |
在 SOAP 客户端中使用
SoapUI
- 选择 File,然后选 New SOAP Project。
- 把
https://api.testingapis.com/api/soap/calculator?wsdl登录后查看 粘贴为 Initial WSDL 并完成。SoapUI 会为两种绑定下的每个操作生成一个请求。 - 打开一个请求,填好
intA和intB,然后运行。
Python 与 zeep
zeep 读取 WSDL 并据此生成带类型的客户端,SOAP fault 会变成 Python 异常:
# pip install zeep
from zeep import Client
client = Client("https://api.testingapis.com/api/soap/calculator?wsdl")
print(client.service.Add(intA=5, intB=3))
print(client.service.Multiply(intA=6, intB=7))
try:
client.service.Divide(intA=10, intB=0)
except Exception as err:
print(type(err).__name__, err)8
42
Fault Attempted to divide by zero.JavaScript 与 fetch
不用 SOAP 库时,请求就是一个 XML 字符串,结果从响应文本中取出:
const envelope = `<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<Multiply xmlns="http://tempuri.org/">
<intA>6</intA>
<intB>7</intB>
</Multiply>
</soap:Body>
</soap:Envelope>`;
const res = await fetch("https://api.testingapis.com/api/soap/calculator", {
method: "POST",
headers: {
"Content-Type": "text/xml; charset=utf-8",
SOAPAction: '"http://tempuri.org/Multiply"',
},
body: envelope,
});
const xml = await res.text();
console.log(res.status, xml.match(/<MultiplyResult>(.*?)<\/MultiplyResult>/)[1]);
// 200 42国家服务
计算器只返回数字。要测试嵌套记录的解析,就用国家服务。它有 10 个国家(US、GB、IN、DE、FR、JP、BR、CA、AU 和 ZA)。ListCountries 返回代码和名称,GetCountryInfo 返回一条完整记录:
curl -X POST https://api.testingapis.com/api/soap/countries \
-H 'Content-Type: text/xml' \
-d '<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<GetCountryInfo xmlns="http://example.com/countries">
<countryCode>IN</countryCode>
</GetCountryInfo>
</soap:Body>
</soap:Envelope>'<GetCountryInfoResponse xmlns="http://example.com/countries">
<Country>
<Code>IN</Code>
<Name>India</Name>
<Capital>New Delhi</Capital>
<Currency>INR</Currency>
<PhoneCode>+91</PhoneCode>
<Continent>Asia</Continent>
<Population>1428627663</Population>
</Country>
</GetCountryInfoResponse>未知的代码会返回客户端 fault:
HTTP/1.1 500 Internal Server Error
<soap:Fault>
<faultcode>soap:Client</faultcode>
<faultstring>Country code 'ZZ' not found.</faultstring>
</soap:Fault>相关 API
SOAP API 参考列出了每个操作及可直接发送的信封。要测试通过普通 REST 处理 XML 的客户端,可以试试XML 用户 API。JSON 转 XML 工具有助于把 SOAP 负载和对应的 JSON 进行对比。想从头学习 SOAP,包括 WSDL、fault、XPath 和一套 Java 测试,请看SOAP 与 XML 教程(英文)。