clue / soap-react
简单、异步SOAP Web服务客户端库,基于ReactPHP构建
Requires
- php: >=7.1
- ext-soap: *
- react/http: ^1.0
- react/promise: ^2.1 || ^1.2
Requires (Dev)
- clue/block-react: ^1.0
- phpunit/phpunit: ^9.3 || ^7.5
README
简单、异步SOAP Web服务客户端库,基于ReactPHP构建。
特别值得一提的是,SOAP常用于在分布式系统中调用远程过程调用(RPCs)。内部,SOAP消息被编码为XML,并通过HTTP POST请求发送。就大多数情况而言,SOAP(最初为简单对象访问协议)是一个过时的协议,实际上远非简单。它仍然被许多(通常是旧式)系统使用。此项目提供了一种简单的API来调用异步RPC以调用远程Web服务。
- 异步执行函数 - 并行向远程Web服务发送任意数量的函数(RPCs),并尽快处理结果。基于Promise的设计提供了一个处理无序响应的合理接口。
- 异步处理WSDL - WSDL(Web服务描述语言)文件将在后台下载并处理。
- 事件驱动核心 - 内部,所有操作都使用事件处理器来响应传入的事件,例如传入的RPC结果。
- 轻量级、SOLID设计 - 提供了一个“足够好”的薄层抽象,不会妨碍你。基于经过测试的组件构建,而不是重新发明轮子。
- 良好的测试覆盖率 - 附带自动测试套件,并定期针对实际野外的Web服务进行测试。
目录
支持我们
我们在开发、维护和更新我们出色的开源项目上投入了大量时间。您可以通过在GitHub上成为赞助者来帮助我们维持我们工作的这种高质量。赞助者将获得许多回报,有关详情请参阅我们的赞助页面。
让我们共同将这些项目提升到新的水平!🚀
快速入门示例
安装后,您可以使用以下代码通过SOAP查询示例Web服务
<?php require __DIR__ . '/vendor/autoload.php'; $browser = new React\Http\Browser(); $wsdl = 'http://example.com/demo.wsdl'; $browser->get($wsdl)->then(function (Psr\Http\Message\ResponseInterface $response) use ($browser) { $client = new Clue\React\Soap\Client($browser, (string)$response->getBody()); $api = new Clue\React\Soap\Proxy($client); $api->getBank(array('blz' => '12070000'))->then(function ($result) { var_dump('Result', $result); }); });
另请参阅示例。
用法
客户端
Client
类负责与远程SOAP Web服务服务器通信。它需要WSDL文件内容以及可选的SOAP选项数组
$wsdl = '<?xml …'; $options = array(); $client = new Clue\React\Soap\Client(null, $wsdl, $options);
这个类接受一个可选的 Browser|null $browser
参数,可以用来将浏览器实例传递给这个对象。如果您需要自定义连接器设置(DNS解析、TLS参数、超时、代理服务器等),您可以显式地传递一个自定义的 ConnectorInterface
实例给 Browser
实例,并将其作为额外的参数传递给 Client
,如下所示
$connector = new React\Socket\Connector(array( 'dns' => '127.0.0.1', 'tcp' => array( 'bindto' => '192.168.10.1:0' ), 'tls' => array( 'verify_peer' => false, 'verify_peer_name' => false ) )); $browser = new React\Http\Browser($connector); $client = new Clue\React\Soap\Client($browser, $wsdl);
Client
与 PHP 的 SoapClient
(它在底层使用)类似,但它将加载 WSDL 文件的责任留给了您。这允许您使用本地 WSDL 文件、缓存中的 WSDL 文件或最常见的格式,通过 Browser
从 URL 下载 WSDL 文件内容
$browser = new React\Http\Browser(); $browser->get($url)->then( function (Psr\Http\Message\ResponseInterface $response) use ($browser) { // WSDL file is ready, create client $client = new Clue\React\Soap\Client($browser, (string)$response->getBody()); // do something… }, function (Exception $e) { // an error occured while trying to download the WSDL } );
Client
构造函数将给定的 WSDL 文件内容加载到内存中,并解析其定义。如果给定的 WSDL 文件无效且无法解析,这将抛出 SoapFault
try { $client = new Clue\React\Soap\Client(null, $wsdl); } catch (SoapFault $e) { echo 'Error: ' . $e->getMessage() . PHP_EOL; }
注意,如果您已加载旧版本的
ext-xdebug
< 2.7,则可能会发生致命错误而不是抛出SoapFault
。不建议在生产环境中使用此扩展,因此这应该只会影响测试环境。
Client
构造函数接受一个选项数组。所有给定的选项都将传递到底层的 SoapClient
。然而,并非所有选项都适用于此异步实现,因此可能不会产生预期效果。有关更多详细信息,请参阅 SoapClient
文档。
如果以 WSDL 模式工作,则 $options
参数是可选的。如果以非 WSDL 模式工作,则必须将 WSDL 参数设置为 null
,并且选项参数必须包含 location
和 uri
选项,其中 location
是发送请求的 SOAP 服务器 URL,而 uri
是 SOAP 服务的目标命名空间
$client = new Clue\React\Soap\Client(null, null, array( 'location' => 'http://example.com', 'uri' => 'http://ping.example.com', ));
同样,如果以 WSDL 模式工作,可以使用 location
选项显式地覆盖发送请求的 SOAP 服务器 URL
$client = new Clue\React\Soap\Client(null, $wsdl, array( 'location' => 'http://example.com' ));
您可以使用 soap_version
选项从默认的 SOAP 1.1 更改为使用 SOAP 1.2
$client = new Clue\React\Soap\Client(null, $wsdl, array( 'soap_version' => SOAP_1_2 ));
您可以使用 classmap
选项将某些 WSDL 类型映射到 PHP 类,如下所示
$client = new Clue\React\Soap\Client(null, $wsdl, array( 'classmap' => array( 'getBankResponseType' => BankResponse::class ) ));
proxy_host
选项(及其家族)不支持此库。作为替代,您可以配置给定的 $browser
实例以使用一个 HTTP 代理服务器。如果您发现此处缺少或不受支持的任何其他选项,请提交 PR,我们将不胜感激!
Client
的所有公共方法都被视为 高级用法。如果您想调用 RPC 函数,请参阅下面的 Proxy
类。
soapCall()
可以使用 soapCall(string $method, mixed[] $arguments): PromiseInterface<mixed, Exception>
方法将给定的函数排队以通过 SOAP 发送,并等待远程 web 服务的响应。
// advanced usage, see Proxy for recommended alternative $promise = $client->soapCall('ping', array('hello', 42));
注意:这被视为 高级用法,您可能想考虑使用 Proxy
。
$proxy = new Clue\React\Soap\Proxy($client); $promise = $proxy->ping('hello', 42);
getFunctions()
可以使用 getFunctions(): string[]|null
方法返回在 WSDL 中定义的函数数组。
它返回 PHP 的 SoapClient::__getFunctions()
的等效内容。在非 WSDL 模式下,此方法返回 null
。
getTypes()
可以使用 getTypes(): string[]|null
方法返回在 WSDL 中定义的类型数组。
该方法返回PHP的SoapClient::__getTypes()
的等效值。在非WSDL模式下,此方法返回null
。
getLocation()
getLocation(string|int $function): string
方法可用于返回指定的web服务$function
的位置(URI)。
注意,这不要与WSDL文件的位置混淆。WSDL文件可以包含任意数量的函数定义。所有这些函数使用相同的定位定义是非常常见的。然而,在技术上,每个函数都可以使用不同的位置。
$function
参数应该是一个包含SOAP函数名的字符串。有关所有可用函数的列表,请参阅getFunctions()
。
assert('http://example.com/soap/service' === $client->getLocation('echo'));
为了便于访问,此函数还接受一个数字函数索引。然后它内部使用getFunctions()
来获取给定索引的函数名。这对于所有函数使用相同的位置,并且访问第一个位置就足够的情况特别有用。
assert('http://example.com/soap/service' === $client->getLocation(0));
当在Client
构造函数中设置了location
选项(例如,在非WSDL模式下)或通过withLocation()
方法时,此方法返回给定位置的价值。
传递未在WSDL文件中定义的$function
将抛出SoapFault
。
withLocation()
可以使用withLocation(string $location): self
方法返回具有所有函数更新位置(URI)的新Client
。
注意,这不要与WSDL文件的位置混淆。WSDL文件可以包含任意数量的函数定义。所有这些函数使用相同的定位定义是非常常见的。然而,在技术上,每个函数都可以使用不同的位置。
$client = $client->withLocation('http://example.com/soap'); assert('http://example.com/soap' === $client->getLocation('echo'));
作为此方法的替代,您还可以在Client
构造函数中设置location
选项(例如,在非WSDL模式下)。
withHeaders()
可以使用withHeaders(array $headers): self
方法返回具有所有函数更新头的新Client
。这允许设置某些SOAP端点所需的具体头,例如用于身份验证等。
$client = $client->withHeaders([new SoapHeader(...)]);
代理
Proxy
类封装现有的Client
实例,以便简化调用SOAP函数。
$proxy = new Clue\React\Soap\Proxy($client);
请注意,此类被称为“Proxy”,因为它将所有方法调用通过底层的
Client::soapCall()
方法转发(代理)到实际的SOAP服务。这不要与使用代理服务器混淆。有关如何使用HTTP代理服务器,请参阅Client
文档的更多详细信息。
函数
对Proxy
类的每个方法调用都将通过SOAP发送。
$proxy->myMethod($myArg1, $myArg2)->then(function ($response) { // result received });
请参考您的WSDL或其相关文档,以了解哪些函数和参数受支持。
承诺
发出SOAP函数是异步的(非阻塞的),因此您可以实际上并行发送多个RPC请求。web服务将对每个请求响应一个返回值。顺序没有保证。发送请求使用基于Promise的接口,这使得在请求满足(即成功解决或因错误拒绝)时进行响应变得容易。
$proxy->demo()->then( function ($response) { // response received for demo function }, function (Exception $e) { // an error occured while executing the request } });
取消
返回的Promise是以一种方式实现的,可以取消其挂起状态。取消挂起的Promise将使用异常拒绝其值,并清理任何底层资源。
$promise = $proxy->demo(); Loop::addTimer(2.0, function () use ($promise) { $promise->cancel(); });
超时
这个库使用了一个非常高效的HTTP实现,因此大多数SOAP请求通常只需毫秒即可完成。然而,当通过不可靠的网络(互联网)发送SOAP请求时,可能会出现一些问题,这可能导致请求在一段时间后失败。因此,超时由底层HTTP库处理,并且这个库尊重PHP的default_socket_timeout
设置(默认60秒)作为发送出站SOAP请求和等待成功响应的超时时间,否则将取消挂起的请求并以异常拒绝其值。
请注意,此超时值涵盖了创建底层传输连接、发送SOAP请求、等待远程服务处理请求和接收完整的SOAP响应。要使用自定义超时值,可以将超时值传递给底层的Browser
,如下所示
$browser = new React\Http\Browser(); $browser = $browser->withTimeout(10.0); $client = new Clue\React\Soap\Client($browser, $wsdl); $proxy = new Clue\React\Soap\Proxy($client); $proxy->demo()->then(function ($response) { // response received within 10 seconds maximum var_dump($response); });
同样,您可以使用负的超时值来不应用超时,或使用null
值来恢复默认处理。请注意,底层连接可能还会强制不同的超时值。有关更多详细信息,请参阅底层的超时文档。
安装
推荐通过Composer安装此库。你是Composer的新手吗?
此项目遵循SemVer。这将安装最新支持的版本
$ composer require clue/soap-react:^2.0
有关版本升级的详细信息,请参阅CHANGELOG。
此项目旨在在所有平台上运行,因此仅需要ext-soap
并支持在PHP 7.1+上运行。
测试
要运行测试套件,您首先需要克隆此存储库,然后通过Composer安装所有依赖项
$ composer install
要运行测试套件,请转到项目根目录并运行
$ php vendor/bin/phpunit
测试套件还包含一些功能集成测试,这些测试依赖于稳定的互联网连接。如果您不想运行这些测试,可以简单地像这样跳过它们
$ php vendor/bin/phpunit --exclude-group internet
许可
此项目根据宽松的MIT许可证发布。
你知道吗?我可以提供定制开发服务,并为发布赞助和贡献开具发票。如需详细了解,请联系我(@clue)。