一个带 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登录后查看
WSDLGET /api/soap/calculator?wsdl登录后查看没有。对端点发 GET 可获得用法说明 JSON 和示例信封
命名空间http://tempuri.org/http://example.com/countries
操作Add、Subtract、Multiply、Divide(整数)GetCountryInfo(countryCode)、ListCountries()
版本SOAP 1.1 和 1.2SOAP 1.1 和 1.2

用 curl 调用(SOAP 1.1)

SOAP 1.1 使用 Content-Type: text/xml,以及一个指明操作名的 SOAPAction 请求头。这里这个请求头是可选的,但如果发送,它必须与请求体中的操作一致。

Terminal
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:

Terminal
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.1SOAP 1.2
输入错误(未知的国家代码)500,faultcode soap:Client400,Code soap:Sender
服务器端错误(除以零)500,faultcode soap:Server500,Code soap:Receiver
SOAPAction 指向另一个操作500 fault不适用
Content-Type 错误(如 JSON)带 JSON 错误的 415带 JSON 错误的 415

在 SOAP 客户端中使用

SoapUI

  1. 选择 File,然后选 New SOAP Project。
  2. 把 https://api.testingapis.com/api/soap/calculator?wsdl登录后查看 粘贴为 Initial WSDL 并完成。SoapUI 会为两种绑定下的每个操作生成一个请求。
  3. 打开一个请求,填好 intA 和 intB,然后运行。

Python 与 zeep

zeep 读取 WSDL 并据此生成带类型的客户端,SOAP fault 会变成 Python 异常:

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 字符串,结果从响应文本中取出:

JavaScript
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 返回一条完整记录:

Terminal
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>'
这个示例使用的是面向已登录成员的端点。登录创建免费账户
响应体(在 soap:Body 内)
<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:

countryCode 为 ZZ 时的响应
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 教程(英文)。