创建一个Soap端点#

作者:

fjf2002

PostgREST支持 媒体类型处理程序 。只需做一些工作,就可以实现SOAP端点。

最小示例#

此示例将只返回标记内的请求正文 therequestbodywas

将以下函数添加到您的PostgreSQL数据库:

create domain "text/xml" as pg_catalog.xml;

CREATE OR REPLACE FUNCTION my_soap_endpoint(xml) RETURNS "text/xml" AS $$
DECLARE
  nsarray CONSTANT text[][] := ARRAY[
    ARRAY['soapenv', 'http://schemas.xmlsoap.org/soap/envelope/']
  ];
BEGIN
  RETURN xmlelement(
    NAME "soapenv:Envelope",
    XMLATTRIBUTES('http://schemas.xmlsoap.org/soap/envelope/' AS "xmlns:soapenv"),
    xmlelement(NAME "soapenv:Header"),
    xmlelement(
      NAME "soapenv:Body",
      xmlelement(
        NAME theRequestBodyWas,
        (xpath('/soapenv:Envelope/soapenv:Body', $1, nsarray))[1]
      )
    )
 );
END;
$$ LANGUAGE plpgsql;

别忘了刷新 PostgREST schema cache

使用 curl 对于第一次测试:

curl http://localhost:3000/rpc/my_soap_endpoint \
    --header 'Content-Type: text/xml' \
    --header 'Accept: text/xml' \
    --data-binary @- <<XML
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
  <soapenv:Header/>
  <soapenv:Body>
    <mySOAPContent>
      My SOAP Content
    </mySOAPContent>
  </soapenv:Body>
</soapenv:Envelope>
XML

输出中应包含原始请求正文 therequestbodywas 实体,应该大致如下所示:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
  <soapenv:Header/>
  <soapenv:Body>
    <therequestbodywas>
      <soapenv:Body xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
        <mySOAPContent>
          My SOAP Content
        </mySOAPContent>
      </soapenv:Body>
    </therequestbodywas>
  </soapenv:Body>
</soapenv:Envelope>

一个更详细的例子#

在这里,我们有一个将小数转换为十进制值的SOAP服务,并将PostgreSQL错误传递给SOAP响应。请注意,在生产中,您可能不应该传递可能向客户端泄漏内部信息的普通数据库错误,而应该直接处理这些错误。

-- helper function
CREATE OR REPLACE FUNCTION _soap_envelope(body xml)
 RETURNS xml
 LANGUAGE sql
AS $function$
  SELECT xmlelement(
    NAME "soapenv:Envelope",
    XMLATTRIBUTES('http://schemas.xmlsoap.org/soap/envelope/' AS "xmlns:soapenv"),
    xmlelement(NAME "soapenv:Header"),
    xmlelement(NAME "soapenv:Body", body)
  );
$function$;

-- helper function
CREATE OR REPLACE FUNCTION _soap_exception(
  faultcode text,
  faultstring text
)
 RETURNS xml
 LANGUAGE sql
AS $function$
  SELECT _soap_envelope(
    xmlelement(NAME "soapenv:Fault",
      xmlelement(NAME "faultcode", faultcode),
      xmlelement(NAME "faultstring", faultstring)
    )
  );
$function$;

CREATE OR REPLACE FUNCTION fraction_to_decimal(xml)
 RETURNS "text/xml"
 LANGUAGE plpgsql
AS $function$
DECLARE
  nsarray CONSTANT text[][] := ARRAY[
    ARRAY['soapenv', 'http://schemas.xmlsoap.org/soap/envelope/']
  ];
  exc_msg text;
  exc_detail text;
  exc_hint text;
  exc_sqlstate text;
BEGIN
  -- simulating a statement that results in an exception:
  RETURN _soap_envelope(xmlelement(
    NAME "decimalValue",
    (
      (xpath('/soapenv:Envelope/soapenv:Body/fraction/numerator/text()', $1, nsarray))[1]::text::int
      /
      (xpath('/soapenv:Envelope/soapenv:Body/fraction/denominator/text()', $1, nsarray))[1]::text::int
    )::text::xml
  ));
EXCEPTION WHEN OTHERS THEN
  GET STACKED DIAGNOSTICS
    exc_msg := MESSAGE_TEXT,
    exc_detail := PG_EXCEPTION_DETAIL,
    exc_hint := PG_EXCEPTION_HINT,
    exc_sqlstate := RETURNED_SQLSTATE;
  RAISE WARNING USING
    MESSAGE = exc_msg,
    DETAIL = exc_detail,
    HINT = exc_hint;
  RETURN _soap_exception(faultcode => exc_sqlstate, faultstring => concat(exc_msg, ', DETAIL: ', exc_detail, ', HINT: ', exc_hint));
END
$function$;

让我们来测试一下 fraction_to_decimal 具有非法价值的服务:

curl http://localhost:3000/rpc/fraction_to_decimal \
  --header 'Content-Type: text/xml' \
  --header 'Accept: text/xml' \
  --data-binary @- <<XML
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
  <soapenv:Header/>
  <soapenv:Body>
    <fraction>
      <numerator>42</numerator>
      <denominator>0</denominator>
    </fraction>
  </soapenv:Body>
</soapenv:Envelope>
XML

输出应该大致如下所示:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
  <soapenv:Header/>
  <soapenv:Body>
    <soapenv:Fault>
      <faultcode>22012</faultcode>
      <faultstring>division by zero, DETAIL: , HINT: </faultstring>
    </soapenv:Fault>
  </soapenv:Body>
</soapenv:Envelope>

参考文献#

有关PostgREST的更多信息,请参阅

有关Soap参考,请访问

  • Https://www.w3.org/TR/soap/上的规范

  • 有关更简短、更实用的建议,请访问https://www.w3schools.com/xml/xml_soap.asp