php - WSDL如何设置独立于服务执行url的目标命名空间
问题描述
我必须在 PHP 下设置一个 SOAP 服务器并且我已经让它工作了,但是因为我需要维护与开发、阶段和生产分开的状态,所以它需要从 wsdl 中获取所有真实的 url。我搜索了很多文档,但是我得到的任何示例在 wsdl 中都有目标 url,并且我完成了以下工作 wsdl
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="https://example.com/ws/OCService/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="OCService" targetNamespace="https://example.com/ws/OCService/">
<wsdl:types>
<xsd:schema targetNamespace="https://example.com/ws/OCService/">
<xsd:element name="OrderCreation">
<xsd:complexType>
<xsd:annotation>
<xsd:documentation>How to use the server</xsd:documentation>
</xsd:annotation>
<xsd:sequence>
<xsd:element name="name" type="xsd:string"></xsd:element>
<xsd:element name="number" type="xsd:int"></xsd:element>
<xsd:element name="opCode" type="xsd:string"></xsd:element>
<xsd:element name="providerCode" type="xsd:string"></xsd:element>
<xsd:element name="amount" type="xsd:decimal"></xsd:element>
<xsd:element name="currency" type="xsd:string"></xsd:element>
<xsd:element name="term" type="xsd:date"></xsd:element>
<xsd:element name="advance" type="xsd:decimal"></xsd:element>
<xsd:element name="repair" type="xsd:decimal"></xsd:element>
<xsd:element name="fortnight" type="xsd:int"></xsd:element>
<xsd:element name="items" type="tns:orderedItems"></xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="OrderCreationResponse">
<xsd:annotation>
<xsd:documentation>Response: Error or Success</xsd:documentation>
</xsd:annotation>
<xsd:complexType>
<xsd:sequence>
<xsd:element name="result" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:complexType name="Orden">
<xsd:annotation>
<xsd:documentation>General information</xsd:documentation>
</xsd:annotation>
<xsd:sequence>
<xsd:element name="name" type="xsd:string"></xsd:element>
<xsd:element name="number" type="xsd:int"></xsd:element>
<xsd:element name="opCode" type="xsd:string"></xsd:element>
<xsd:element name="providerCode" type="xsd:string"></xsd:element>
<xsd:element name="amount" type="xsd:float"></xsd:element>
<xsd:element name="currency" type="xsd:string"></xsd:element>
<xsd:element name="term" type="xsd:date"></xsd:element>
<xsd:element name="advance" type="xsd:float"></xsd:element>
<xsd:element name="repair" type="xsd:float"></xsd:element>
<xsd:element name="fortnight" type="xsd:int"></xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="Item">
<xsd:annotation>
<xsd:documentation>Item information</xsd:documentation>
</xsd:annotation>
<xsd:sequence>
<xsd:element name="itemName" type="xsd:string" />
<xsd:element name="number" type="xsd:int" />
<xsd:element name="unity" type="xsd:string" />
<xsd:element name="unitPrice" type="xsd:decimal" />
<xsd:element name="quantity" type="xsd:decimal" />
<xsd:element name="itemAmount" type="xsd:decimal" />
<xsd:element name="itemOrder" type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="orderedItems">
<xsd:annotation>
<xsd:documentation>Array de items que integran la OC</xsd:documentation>
</xsd:annotation>
<xsd:sequence>
<xsd:element name="item" type="tns:Item" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
</wsdl:types>
<wsdl:message name="OrderCreationRequest">
<wsdl:part element="tns:OrderCreation" name="parameters"/>
</wsdl:message>
<wsdl:message name="OrderCreationResponse">
<wsdl:part element="tns:OrderCreationResponse" name="parameters"/>
</wsdl:message>
<wsdl:portType name="OCService">
<wsdl:operation name="OrderCreation">
<wsdl:input message="tns:OrderCreationRequest"/>
<wsdl:output message="tns:OrderCreationResponse"/>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="OCServiceSOAP" type="tns:OCService">
<soap:binding style="document"
transport="http://schemas.xmlsoap.org/soap/http" />
<wsdl:operation name="OrderCreation">
<soap:operation
soapAction="https://example.com/ws/OCService/" />
<wsdl:input>
<soap:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="OCService">
<wsdl:documentation>Orders creation service</wsdl:documentation>
<wsdl:port binding="tns:OCServiceSOAP" name="OCServiceSOAP">
<soap:address location="https://example.com/ws/OCService/"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
关键是这种设计虽然可行,但不能满足将执行 url 从 WSDL 表中分离出来的需要,所以当从阶段到生产时,我必须修改 wsdl,这不应该发生,因为要求是保持WSDL 不可变。
有人告诉我,您可以在 http 标头中设置 url,但我不明白这种替代方法是如何工作的。
在这一点上,我将不胜感激。提前致谢。
解决方案
前段时间我遇到了同样的问题。在一个开发团队中,我们讨论了可能的解决方案。一种有前途的方法是使用占位符。我假设你有一个控制器来初始化你的肥皂服务器。即使在初始化之前,您也可以检查请求 URL 是什么。基于此请求 URL,然后可以相应地解析和调整 WSDL。
让我们假设您的服务位置是一个占位符。
<wsdl:service name="OCService">
<wsdl:documentation>Orders creation service</wsdl:documentation>
<wsdl:port binding="tns:OCServiceSOAP" name="OCServiceSOAP">
<soap:address location="{{PLACEHOLDER}}"/>
</wsdl:port>
</wsdl:service>
在你的控制器中,你做这样的事情......
class SoapServerController
{
...
public function initAction(): void
{
// check the request uri
$requestUri = $_SERVER['REQUEST_URI'];
switch ($requestUri) {
case 'yadda' :
$environment = 'staging';
$locationUri = 'https://example.com/A';
break;
case 'blubb' :
$environment = 'production';
$locationUri = 'https://example.com/B';
break;
default :
$environment = 'test';
$locationUri = 'https://example.com/C';
break;
}
// rewrite the wsdl
$doc = new DOMDocument();
$doc->loadXML('https://some.location.tld/inital.wsdl');
$address = $doc->getElementsByTagNameNS('http://schemas.xmlsoap.org/wsdl/soap/', 'address');
$adress->setAttribute('location', $locationUri);
$filename = PATH_TO_WSDL_FOLDER . '/' . $environment . '.wsdl';
$doc->save($filename);
// is the wsdl get parameter set?
if (isset($_GET['wsdl'])) {
echo $doc->saveXML();
exit();
}
// initialize the soap server
$service = new SoapService();
$server = new SoapServer($filename, []);
$server->setObject($service);
$server->handle();
}
}
请记住,这只是未经测试的示例代码。然而,团队决定为每个环境创建一个 WSDL 文件并放弃逻辑,因为为每个请求编写一个新的 WSDL 文件将带来太多的技术债务。即使使用了缓存系统。我们选择了速度和可维护、简单的代码。我不知道你要处理多少环境。对我们来说,处理四个不同的 wsdl 文件更容易。
推荐阅读
- php - 将自定义表单字段发送到 paytm 并获得 Paytm 的响应问题
- multidimensional-array - xarray 数据集:对数据变量进行分面绘图 (data_vars)
- javascript - Javascript多输入计算器,输入由用户生成,然后这些输入应该进行计算
- vb.net - 如何在ms access数据库中按单个日期搜索?
- mysql-python - 在访问 MySQL 数据库时,使用 Python 在 where 子句中将变量传递给 SQL 选择查询
- django - 在 django 项目中将西里尔字体从 html 页面渲染为 pdf
- java - 如何在时间间隔内管理 Firestore 数据库中文档的离线更新状态
- flutter - 如何创建从侧面打开的模态底页
- javascript - NextJS - 错误:对象作为 React 子项无效(找到:带有键 {items} 的对象)
- nunjucks - 页