php - 为什么 __soapCall 抛出“Forbidden”而 __doRequest 成功?
问题描述
让我们考虑下面的 SOAP 客户端示例。它基本上扩展了 PHP 原生版本(注意我们处于wsdl
模式):
use SoapClient;
use SoapFault;
abstract class AbstractClient extends SoapClient
{
abstract protected function getHeaders(): array;
private function call(string $functionName, array $arguments)
{
$this->__setSoapHeaders(
$this->getHeaders()
);
try {
return $this->__soapCall($functionName, [$arguments]);
} catch (SoapFault $soapFault) {
// ...
}
}
public function sendRequest(string $functionName, array $arguments)
{
return $this->call($functionName, $arguments);
}
}
使用请求 SOAP 服务器__soapCall
不断抛出SoapFault
:
faultstring: Forbidden
faultcode: HTTP
我尝试了不同的配置、更改缓存、SOAP 版本、SSL 流上下文等,但仍然无济于事。
现在,想象用 请求同一个端点__doRequest
,传递使用先前实现生成的 XML 请求(XML 是从$this->__getLastRequest()
catch 部分中转储的),然后它可以工作,我们从服务器获得预期的响应。
从那里,我覆盖了__doRequest
客户端(__doRequest
由 PHP 在较低级别调用以执行__soapCall
)以查看有什么区别:
public function __doRequest($request, $location, $action, $version, $one_way = 0)
{
// Output $request, $location, $action, $version and $one_way
parent::__doRequest($request, $location, $action, $version, $one_way);
}
事实证明,唯一的一个是缺少$action
空的参数。所以我对其进行了硬编码,但同样无济于事:再次抛出了 Forbidden 异常。
有人知道这里发生了什么吗?
编辑
经过多次测试,我现在可以看出格式化 XML 请求(不是单行,而是它的“美化”版本)确实有效。也许我错过了某种编码/格式化配置,不幸的是 PHP 文档在这个主题上不是很准确......
解决方案
我终于想出了一个肮脏的解决方案。使用以下方法覆盖__doRequest
和格式化请求DOMDocument
:
public function __doRequest($request, $location, $action, $version, $one_way = 0)
{
$xml = new DOMDocument();
$xml->preserveWhiteSpace = false;
$xml->formatOutput = true;
$xml->loadXML($request);
$request = $xml->saveXML();
return parent::__doRequest($request, $location, $action, $version, $one_way);
}
有谁知道如何配置 PHP SOAP 扩展来正确实现这一点?
推荐阅读
- java - 可访问和可修改的数据?
- php - 输入表单中的“上传”功能,它在本地网络上创建一个文件夹并在其中存储 pdf,以便基于 PHP/Mysql 的本地网络上的 CRUD 应用程序
- c# - 在地图中生成随机游戏对象(无重复)
- c - 为指针算术生成的程序集
- python - “utf-8”编解码器无法解码位置 28 中的字节 0x80:无效的起始字节
- firebase - firestore 计数如何在颤振上读取
- flutter - 如何使用 cognito 刷新令牌在颤振中获取新的 accessToken
- ios - 页面视图控制器中的子视图控制器无法接收委托调用
- javascript - Javascript 字符串是不可变的,但按索引重新分配不会引发错误
- python - 斜纹导致 print() 不显示