This repository concerns Kong plugins developed in Lua and uses the GNOME C libraries libxml2 and libxslt (for XSLT 1.0). Part of the functions are bound in the XMLua/libxml2 library. Both GNOME C and XMLua/libxml2 libraries are already included in kong/kong-gateway Enterprise Edition Docker image, so you don't need to rebuild a Kong image.
The XSLT Transformation can also be managed with the saxon library, which supports XSLT 2.0 and 3.0. With XSLT 2.0+ there is a way for applying JSON <-> XML transformation with fn:json-to-xml and fn:xml-to-json. The saxon
library is not included in the Kong Docker image, see SAXON.md for how to integrate saxon with Kong. It's optional, don't install the saxon
library if you don't need it.
These plugins don't apply to Kong OSS. They work for Kong EE and Konnect.
The plugins handle the SOAP/XML Request and/or the SOAP/XML Response in this order:
soap-xml-request-handling plugin to handle Request:
XSLT TRANSFORMATION - BEFORE XSD
: Transform the XML request with XSLT (XSLTransformation) before step #2WSDL/XSD VALIDATION
: Validate XML request with its WSDL/XSD schema (and optionnaly validate theSOAPAction
header)XSLT TRANSFORMATION - AFTER XSD
: Transform the XML request with XSLT (XSLTransformation) after step #2ROUTING BY XPATH
: change the Route of the request to a different hostname and path depending of XPath condition
soap-xml-response-handling plugin to handle Reponse:
XSLT TRANSFORMATION - BEFORE XSD
: Transform the XML response before step #6WSDL/XSD VALIDATION
: Validate the XML response with its WSDL/XSD schemaXSLT TRANSFORMATION - AFTER XSD
: Transform the XML response after step #6
Each handling is optional. In case of misconfiguration the Plugin sends to the consumer an HTTP 500 Internal Server Error <soap:Fault>
(with the error detailed message).
- Configuration Reference
- How to deploy SOAP/XML Handling plugins
- Quick Test: How to test an XML calculator Web Service without the plugins
- Main Example: How to test XML Handling plugins with calculator
- Example #1: Request | XSLT TRANSFORMATION - BEFORE XSD
- Example #2: Request | XSD VALIDATION
- Example #3: Request | XSLT TRANSFORMATION - AFTER XSD
- Example #4: Request | ROUTING BY XPATH
- Example #5: Response | XSLT TRANSFORMATION - BEFORE XSD
- Example #6: Response | XSD VALIDATION
- Example #7: Response | XSLT TRANSFORMATION - AFTER XSD
- Miscellaneous examples
- Example (A) : Response | Use a SOAP/XML WebService with gzip
- Example (B) : Request | Use a WSDL definition, which imports an XSD schema from an external entity
- Example (C1): Request | Use a WSDL definition, which imports an XSD schema from the plugin configuration
- Example (C2): Request | Use a WSDL definition, which imports an XSD schema from the plugin configuration for KIC
- Example (D) : Request and Response | XSLT with the saxon library
- Example (E) : Request and Response | use a SOAP 1.2 XSD definition and the calculator API XSD definition
- Example (F) : Request | validate the SOAPAction Http header
- Example (G): Request | XSLT with parameters applied by libxslt (or saxon) library
- W3C Compatibility Matrix
- Plugins Testing
- Known Limitations
- Changelog
FORM PARAMETER | DEFAULT | DESCRIPTION |
---|---|---|
config.ExternalEntityLoader_Async | false |
Download asynchronously the XSD schema from an external entity (i.e.: http(s)://). It executes a WSDL/XSD validation prefetch on the configure phase (for downloading the ìmported XSD ahead of the 1st request) |
config.ExternalEntityLoader_CacheTTL | 3600 |
Keep the XSD schema in Kong memory cache during the time specified (in second). It applies for synchronous and asynchronous XSD download |
config.ExternalEntityLoader_Timeout | 1 |
Tiemout in second for XSD schema downloading. It applies for synchronous and asynchronous XSD download |
config.RouteToPath | N/A | URI Path to change the route dynamically to the Web Service. Syntax is: scheme://kong_upstream/path or scheme://hostname:port/path |
config.RouteXPath | N/A | XPath request to extract a value from the request body and to compare it with RouteXPathCondition |
config.RouteXPathCondition | N/A | XPath value to compare with the value extracted by RouteXPath . If the condition is satisfied the route is changed to RouteToPath |
config.RouteXPathRegisterNs | Pre-defined | Register Namespace to enable XPath request. The syntax is prefix,namespace . Mulitple entries are allowed (example: prefix1,namespace1 ,prefix2,namespace2 ). If this is the defauft Namespace without a prefix (like xmlns=http://... instead of xmlns:xsd=http://... ) set a a fake prefix like myprefix,http://... |
config.SOAPAction_Header | no |
soap-xml-request-handling only: validate the value of the SOAPAction Http header in conjonction with WSDL/XSD VALIDATION . If yes is set, the xsdSoapSchema must be defined with a WSDL 1.1 (including <wsdl:binding> and soapAction attributes) or with a WSDL 2.0 (including <wsdl2:interface> and Action attribute). For WSDL 1.1 the optional soapActionRequired attribute is considered and for WSDL 2.0 the default action pattern is used if no Action is set (as defined by the W3C). If yes_null_allowed is set, the plugin works as defined with yes configuration and top of that it allows the request even if the SOAPAction is not present. The SOAPAction = '' is not considered a valid value |
config.VerboseRequest | false |
soap-xml-request-handling only: enable a detailed error message sent to the consumer. The syntax is <detail>...</detail> in the <soap:Fault> message |
config.VerboseResponse | false |
soap-xml-response-handling only: see above |
config.xsdApiSchema | false |
WSDL/XSD schema used by WSDL/XSD VALIDATION for the Web Service tags |
config.xsdApiSchemaInclude | false |
XSD content included in the plugin configuration. It's related to xsdApiSchema . It avoids downloading content from external entity (i.e.: http(s)://). The include has priority over the download from external entity. It's the recommended option instead of using ExternalEntityLoader_Async |
config.xsdSoapSchema | Pre-defined with SOAP v1.1 |
WSDL/XSD schema used by WSDL/XSD VALIDATION for the <soap> tags: <soap:Envelope> , <soap:Header> , <soap:Body> |
config.xsdSoapSchemaInclude | false |
XSD content included in the plugin configuration. It's related to xsdSoapSchema . It avoids downloading content from external entity (i.e.: http(s)://). The include has priority over the download from external entity |
config.xsltLibrary | libxslt |
Library name for XSLT TRANSFORMATION . Select saxon for supporting XSLT 2.0 or 3.0 |
config.xsltParams | N/A | Named parameter (<xsl:param> ) to use in XSL schema. Used by XSLT TRANSFORMATION BEFORE XSD and AFTER XSD |
config.xsltTransformAfter | N/A | XSLT definition used by XSLT TRANSFORMATION - AFTER XSD |
config.xsltTransformBefore | N/A | XSLT definition used by XSLT TRANSFORMATION - BEFORE XSD |
- Do a Git Clone of this repo
git clone https://github.com/jeromeguillaume/kong-plugin-soap-xml-handling.git
- Create and prepare a PostgreDB called
kong-database-soap-xml-handling
. See documentation - Provision a license of Kong Enterprise Edition and put the content in
KONG_LICENSE_DATA
environment variable. The following license is only an example. You must use the following format, but provide your own content
export KONG_LICENSE_DATA='{"license":{"payload":{"admin_seats":"1","customer":"Example Company, Inc","dataplanes":"1","license_creation_date":"2023-04-07","license_expiration_date":"2023-04-07","license_key":"00141000017ODj3AAG_a1V41000004wT0OEAU","product_subscription":"Konnect Enterprise","support_plan":"None"},"signature":"6985968131533a967fcc721244a979948b1066967f1e9cd65dbd8eeabe060fc32d894a2945f5e4a03c1cd2198c74e058ac63d28b045c2f1fcec95877bd790e1b","version":"1"}}'
- Start the standalone Kong Gateway
./start-kong.sh
- Do a Git Clone of this repo (if it’s not done yet):
git clone https://github.com/jeromeguillaume/kong-plugin-soap-xml-handling.git
- Login to Konnect
- Select the
Kong Gateway
in the Gateway Manager - Click on
Plugins
- Click on
+ New Plugin
- Click on
Custom Plugins
- Click on
Create
Custom Plugin - Click on
Select file
and open the schema.lua ofsoap-xml-request-handling
- Click on
Save
Repeat from step #6 and open the schema.lua of soap-xml-response-handling
How to deploy SOAP/XML Handling plugins schema in Konnect (Control Plane) for Kong Ingress Controller (KIC)
- Do a Git Clone of this repo (if it’s not done yet):
git clone https://github.com/jeromeguillaume/kong-plugin-soap-xml-handling.git
- Login to Konnect
- Create a Personal Access Token (starting by
kpat_
) or System Account Access Token (starting byspat_
). See documentation - From the
Overview
page of KIC-Gateway manager page, get the KICid
- Upload the custom plugin schema of
soap-xml-request-handling
by using the Konnect API:
cd ./kong-plugin-soap-xml-handling/kong/plugins/soap-xml-request-handling
https -A bearer -a <**REPLACE_BY_ACCESS_TOKEN_VALUE**> eu.api.konghq.com/v2/control-planes/<**REPLACE_BY_KIC_ID**>/core-entities/plugin-schemas [email protected]
The expected response is:
HTTP/1.1 201 Created
Repeat step #5 with the schema.lua of soap-xml-response-handling
by changing the directory:
cd -
cd ./kong-plugin-soap-xml-handling/kong/plugins/soap-xml-response-handling
- Do a Git Clone of this repo (if it’s not done yet):
git clone https://github.com/jeromeguillaume/kong-plugin-soap-xml-handling.git
- Create
configMaps
configMaps
for the custom plugins (Request and Response)
cd ./kong-plugin-soap-xml-handling/kong/plugins
kubectl -n kong create configmap soap-xml-request-handling --from-file=./soap-xml-request-handling
kubectl -n kong create configmap soap-xml-response-handling --from-file=./soap-xml-response-handling
- Create a
configMap
for the shared library
kubectl -n kong create configmap soap-xml-handling-lib --from-file=./soap-xml-handling-lib
- Include
subdirectories
of the library
cd soap-xml-handling-lib
kubectl -n kong create configmap libxml2ex --from-file=./libxml2ex
kubectl -n kong create configmap libxslt --from-file=./libxslt
- See Kong Gateway in Kubernetes documentation and add the following properties to the helm
values.yaml
:
image:
repository: kong/kong-gateway
...
env:
plugins: bundled,soap-xml-request-handling,soap-xml-response-handling
...
plugins:
configMaps:
- pluginName: soap-xml-request-handling
name: soap-xml-request-handling
- pluginName: soap-xml-response-handling
name: soap-xml-response-handling
- pluginName: soap-xml-handling-lib
name: soap-xml-handling-lib
subdirectories:
- name: libxml2ex
path: libxml2ex
- name: libxslt
path: libxslt
- Execute the
helm
command:
helm install kong kong/kong -n kong --values ./values.yaml
-
Create a Kong Gateway Service named
calculator
with this URL: http://www.dneonline.com:80/calculator.asmx. This simple backend Web Service adds or subtracts 2 numbers. -
Create a Route on the
calculator
Service with thepath
value/calculator
-
Call the
calculator
through the Kong Gateway Route by using httpie tool
http POST http://localhost:8000/calculator \
Content-Type:'text/xml; charset=utf-8' \
--raw '<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<Add xmlns="http://tempuri.org/">
<intA>5</intA>
<intB>7</intB>
</Add>
</soap:Body>
</soap:Envelope>'
The expected result is 12
:
<?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>12</AddResult>
</AddResponse>
</soap:Body>
</soap:Envelope>
If you prefer to use the calculator
Web Service deployed locally in Docker:
- Create a
calculator
container
docker run --network=kong-net -d --name ws-soap-calulator --env X_SOAP_REGION=soap1 -p 8080:8080 jeromeguillaume/ws-soap-calculator
- Create a Kong Gateway Service named
calculator
with this URL: http://ws-soap-calulator:8080/ws - Create a Route on the Service
calculator
with thepath
value/calculator
- Call the
calculator
by seeing example in topic above (How to configure and test onlinecalculator
Web Service in Kong Gateway)
- Configure a Kubernetes
External Service
(to http://www.dneonline.com:80/calculator.asmx) with kic/extService-Calculator-Ingress.yaml and a relatedIngress
kind:
kubectl apply -f kic/extService-Calculator-Ingress.yaml
- Call the
calculator
through the Kong Ingress. See example in topic above (How to configure and test onlinecalculator
Web Service in Kong Gateway). Replacelocalhost:8000
by thehostname:port
of the Kong gateway in Kurbenetes
Apply the following examples for testing all capabilities of both plugins. The examples (from Example #1 to Example #7) are related. So apply Example #1 first, then Example #2 (by keeping the configuration of Example #1), etc.
The plugin applies an XSLT Transformation on XML request before the XSD Validation.
In this example the XSLT adds the value <intB>8</intB>
which will not be present in the request.
Add soap-xml-request-handling
plugin and configure the plugin with:
xsltTransformBefore
property with this XSLT definition:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output version="1.0" method="xml" encoding="utf-8" omit-xml-declaration="no"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="//*[local-name()='intA']">
<xsl:copy-of select="."/>
<intB>8</intB>
</xsl:template>
</xsl:stylesheet>
Use command defined at step #3, remove <intB>7</intB>
, the expected result is no longer 12
but 13
:
<?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>13</AddResult>
</AddResponse>
</soap:Body>
</soap:Envelope>
Example #2: Request | XSD VALIDATION
: calling incorrectly calculator
and detecting issue on the Request with XSD schema
Calling incorrectly calculator
and detecting issue in the Request with XSD schema.
We call incorrectly the Service by injecting a SOAP error; the plugin detects it, sends an error message to the Consumer and Kong doesn't call the SOAP backend API.
Open soap-xml-request-handling
plugin and configure the plugin with:
VerboseRequest
enabledxsdApiSchema
property with this value:
<s:schema elementFormDefault="qualified" targetNamespace="http://tempuri.org/" xmlns:s="http://www.w3.org/2001/XMLSchema">
<s:element name="Add">
<s:complexType>
<s:sequence>
<s:element minOccurs="1" maxOccurs="1" name="intA" type="s:int" />
<s:element minOccurs="1" maxOccurs="1" name="intB" type="s:int" />
</s:sequence>
</s:complexType>
</s:element>
<s:element name="Subtract">
<s:complexType>
<s:sequence>
<s:element minOccurs="1" maxOccurs="1" name="intA" type="s:int" />
<s:element minOccurs="1" maxOccurs="1" name="intB" type="s:int" />
</s:sequence>
</s:complexType>
</s:element>
</s:schema>
Use command defined at step #3, change <soap:Envelope>
by <soap:EnvelopeKong>
and change </soap:Envelope>
by </soap:EnvelopeKong>
=> Kong says:
HTTP/1.1 500 Internal Server Error
...
<faultstring>Request - XSD validation failed</faultstring>
<detail>Error Node: EnvelopeKong, Error code: 1845, Line: 2, Message: Element '{http://schemas.xmlsoap.org/soap/envelope/}EnvelopeKong': No matching global declaration available for the validation root.<detail/>
</soap:Fault>
Use command defined at step #3, remove <intA>5</intA>
=> there is an error because the <intA>
tag has the minOccurs="1"
XSD property and Kong says:
HTTP/1.1 500 Internal Server Error
...
<faultstring>Request - XSD validation failed</faultstring>
<detail>Error Node: Add, Error code: 1871, Line: 1, Message: Element '{http://tempuri.org/}Add': Missing child element(s). Expected is ( {http://tempuri.org/}intA ).<detail/>
The plugin applies an XSLT Transformation on XML request after the XSD Validation.
In this example we change the Tag name from <Subtract>...</Subtract>
(present in the request) to <Add>...</Add>
.
Without XSLT: Use command defined at step #3, rename the Tag <Add>...</Add>
, to <Subtract>...</Subtract>
, remove <b>7</b>
, so the new command is:
http POST http://localhost:8000/calculator \
Content-Type:'text/xml; charset=utf-8' \
--raw "<?xml version=\"1.0\" encoding=\"utf-8\"?>
<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">
<soap:Body>
<Subtract xmlns=\"http://tempuri.org/\">
<intA>5</intA>
</Subtract>
</soap:Body>
</soap:Envelope>"
The expected result is -3
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" ...>
<soap:Body>
<SubtractResponse xmlns="http://tempuri.org/">
<SubtractResult>-3</SubtractResult>
</SubtractResponse>
</soap:Body>
</soap:Envelope>
Open soap-xml-request-handling
plugin and configure the plugin with:
xsltTransformAfter
property with this XSLT definition:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="utf-8" omit-xml-declaration="no" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="//*[local-name()='Subtract']">
<Add xmlns="http://tempuri.org/"><xsl:apply-templates select="@*|node()" /></Add>
</xsl:template>
</xsl:stylesheet>
With XSLT: Use command defined at Example #3, the expected result is 13
:
<?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>13</AddResult>
</AddResponse>
</soap:Body>
</soap:Envelope>
Example #4: Request | ROUTING BY XPATH
: change the Route of the request to a different hostname and path depending of XPath condition
The plugin searches the XPath entry and compares it to a Condition value. If this is the right Condition value, the plugin changes the host and the path of the Route.
This example uses a new backend Web Service (https://calculator.apim.eu:443/ws), which provides the same capabilities as calculator
Service (http://www.dneonline.com) defined at step #1.
Add a Kong Upstream
named calculator.apim.eu
and defines a target
with calculator.apim.eu:443
value.
Open soap-xml-request-handling
plugin and configure the plugin with:
RouteToPath
property with the valuehttps://calculator.apim.eu:443/ws
RouteXPath
property with the value/soap:Envelope/soap:Body/*[local-name() = 'Add']/*[local-name() = 'intA']
RouteXPathCondition
property with the value5
RouteXPathRegisterNs
leave the default value; we can also register specific NameSpace with the syntaxprefix,uri
Use command defined at Example #3, the expected result is13
. Pay attention to theX-SOAP-Region
(http header in the response) added bycalculator.apim.eu
HTTP/1.1 200
X-SOAP-Region: soap1.apim.eu
...
<?xml version="1.0" encoding="utf-8" ?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soap:Body>
<AddResponse xmlns="http://tempuri.org/">
<AddResult>13</AddResult>
</AddResponse>
</soap:Body>
</soap:Envelope>
For testing purposes only: one can play with the RouteToPath
to raise a 503 error by temporarily replacing calculator.apim.eu
by calculator.apim.eu.WXYZ
Example #5: Response | XSLT TRANSFORMATION - BEFORE XSD
: changing a Tag name in XML response by using XSLT
The plugin applies an XSLT Transformation on XML response before the XSD Validation. In this example the XSLT changes the Tag names:
- from
<AddResult>...</AddResult>
(present in the response) to<KongResult>...</KongResult>
Add soap-xml-response-handling
plugin and configure the plugin with:
VerboseResponse
enabledxsltTransformBefore
property with this XSLT definition:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="utf-8" omit-xml-declaration="no" indent="yes"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="//*[local-name()='AddResult']">
<KongResult><xsl:apply-templates select="@*|node()" /></KongResult>
</xsl:template>
</xsl:stylesheet>
Use command defined at Example #3, the expected result is <KongResult>13</KongResult>
:
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soap:Body>
<AddResponse xmlns="http://tempuri.org/">
<KongResult>13</KongResult>
</AddResponse>
</soap:Body>
</soap:Envelope>
Open soap-xml-response-handling
plugin and configure the plugin with:
xsdApiSchema
property with this value:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" targetNamespace="http://tempuri.org/" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="AddResponse" type="tem:AddResponseType" xmlns:tem="http://tempuri.org/"/>
<xs:complexType name="AddResponseType">
<xs:sequence>
<xs:element type="xs:string" name="KongResult"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
For testing purposes only: one can play with the XSD schema to raise an error by temporarily replacing KongResult
by KongResult2
Example #7: Response | XSLT TRANSFORMATION - AFTER XSD
: transforming the SOAP response to a XML response
In this example the XSLT removes all tags and converts the response from SOAP to XML.
Open soap-xml-response-handling
plugin and configure the plugin with:
xsltTransformAfter
property with this value:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" exclude-result-prefixes="soapenv">
<xsl:strip-space elements="*"/>
<xsl:output method="xml" version="1.0" encoding="utf-8" omit-xml-declaration="no" indent="yes"/>
<!-- remove all elements in the soapenv namespace -->
<xsl:template match="soapenv:*">
<xsl:apply-templates select="node()"/>
</xsl:template>
<!-- for the remaining elements (i.e. elements in the default namespace) ... -->
<xsl:template match="*">
<!-- ... create a new element with similar name in no-namespace -->
<xsl:element name="{local-name()}">
<xsl:apply-templates select="@*|node()"/>
</xsl:element>
</xsl:template>
<!-- convert attributes to elements -->
<xsl:template match="@*">
<xsl:element name="{local-name()}">
<xsl:value-of select="." />
</xsl:element>
</xsl:template>
</xsl:stylesheet>
Use command defined at Example #3, the expected result is:
<?xml version="1.0" encoding="utf-8"?>
<addResponse>
<KongResult>13</KongResult>
</addResponse>
With Content-Encondig: gzip
the SOAP/XML Response body is zipped. So the soap-xml-response-handling
has to unzip the SOAP/XML Response body, applies XSD and XSLT handling and re-zips the SOAP/XML Response body.
In this example the XSLT converts the response from SOAP to XML
-
Create a new Kong Service named
apim.eu.calculator
with this URL: https://calculator.apim.eu:443/ws, which provides thegzip
support and the same capabilities ascalculator
Service (http://www.dneonline.com) defined at step #1 -
Create a Route on the Service
apim.eu.calculator
with thepath
value/apim.eu.calculator
-
Add
soap-xml-response-handling
plugin and configure the plugin with:
xsltTransformAfter
property with this XSLT definition:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" exclude-result-prefixes="soapenv">
<xsl:strip-space elements="*"/>
<xsl:output method="xml" version="1.0" encoding="utf-8" omit-xml-declaration="no" indent="yes"/>
<!-- remove all elements in the soapenv namespace -->
<xsl:template match="soapenv:*">
<xsl:apply-templates select="node()"/>
</xsl:template>
<!-- for the remaining elements (i.e. elements in the default namespace) ... -->
<xsl:template match="*">
<!-- ... create a new element with similar name in no-namespace -->
<xsl:element name="{local-name()}">
<xsl:apply-templates select="@*|node()"/>
</xsl:element>
</xsl:template>
<!-- convert attributes to elements -->
<xsl:template match="@*">
<xsl:element name="{local-name()}">
<xsl:value-of select="." />
</xsl:element>
</xsl:template>
</xsl:stylesheet>
- Call the
apim.eu.calculator
through the Kong Gateway Route by using httpie tool
http POST http://localhost:8000/apim.eu.calculator \
Content-Type:'text/xml; charset=utf-8' \
--raw '<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<Multiply xmlns="http://tempuri.org/">
<intA>5</intA>
<intB>7</intB>
</Multiply>
</soap:Body>
</soap:Envelope>'
The expected result is zipped with Content-Encoding: gzip
header and we get an XML response (without SOAP tags)
...
HTTP/1.1 200 OK
Content-Encoding: gzip
...
<?xml version="1.0" encoding="utf-8"?>
<MultiplyResponse>
<MultiplyResult>35</MultiplyResult>
</MultiplyResponse>
Example (B): Request | WSDL VALIDATION
: use a WSDL definition, which imports an XSD schema from an external entity (i.e.: http(s)://)
Call correctly calculator
and detect issue in the Request with a WSDL definition. The XSD schema content is not configured in the plugin itself but it's downloaded from an external entity.
In this example we use the Kong Gateway itself to serve the XSD schema (through the WSDL definition), see the import in wsdl
<xsd:import namespace="http://tempuri.org/" schemaLocation="http://localhost:8000/tempuri.org.request-response.xsd"/>
-
Create a Kong Route named
tempuri.org.request-response.xsd
with thepath
value/tempuri.org.request-response.xsd
-
Add
Request Termination
plugin to this Route and configure the plugin with:
body
property with thisXSD
value:
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" targetNamespace="http://tempuri.org/" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="Add" type="tem:AddType" xmlns:tem="http://tempuri.org/"/>
<xs:complexType name="AddType">
<xs:sequence>
<xs:element type="xs:integer" name="intA" minOccurs="1"/>
<xs:element type="xs:integer" name="intB" minOccurs="1"/>
</xs:sequence>
</xs:complexType>
<xs:element name="Subtract" type="tem:SubtractType" xmlns:tem="http://tempuri.org/"/>
<xs:complexType name="SubtractType">
<xs:sequence>
<xs:element type="xs:integer" name="intA" minOccurs="1"/>
<xs:element type="xs:integer" name="intB" minOccurs="1"/>
</xs:sequence>
</xs:complexType>
<xs:element name="AddResponse" type="tem:AddResponseType" xmlns:tem="http://tempuri.org/"/>
<xs:complexType name="AddResponseType">
<xs:sequence>
<xs:element type="xs:string" name="AddResult"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
content_type
property with the valuetext/xml
status_code
property with the value200
-
'Reset' the configuration of
calculator
: remove thesoap-xml-request-handling
andsoap-xml-response-handling
plugins -
Add
soap-xml-request-handling
plugin tocalculator
and configure the plugin with:
ExternalEntityLoader_CacheTTL
property with the value15
secondsVerboseRequest
enabledxsdApiSchema
property with thisWSDL
value:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="http://tempuri.org/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
name="Tempuri.org"
targetNamespace="http://tempuri.org/">
<wsdl:documentation>Tempuri.org - Add and Subtract calculation
</wsdl:documentation>
<wsdl:types>
<!-- XSD schema for the Request and the Response -->
<xsd:schema
xmlns:tns="http://schemas.xmlsoap.org/soap/envelope/"
targetNamespace="http://schemas.xmlsoap.org/soap/envelope/"
attributeFormDefault="qualified"
elementFormDefault="qualified">
<xsd:import namespace="http://tempuri.org/" schemaLocation="http://localhost:8000/tempuri.org.request-response.xsd"/>
</xsd:schema>
</wsdl:types>
</wsdl:definitions>
- check prerequisite: have at least 2 Nginx worker processes because the External Entity loader uses the
socket.http
library which is a blocking library.
KONG_NGINX_WORKER_PROCESSES=2
Note:
- The non-blocking
resty.http
library cannot be used because it raises a conflict issue withlibxml2
:attempt to yield across C-call boundary
- To avoid this limitation please enable the experimental
ExternalEntityLoader_Async
property (which usesresty.http
) or useconfig.xsdApiSchemaInclude
andconfig.xsdSoapSchemaInclude
- Call the
calculator
through the Kong Gateway Route
http POST http://localhost:8000/calculator \
Content-Type:'text/xml; charset=utf-8' \
--raw '<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<Add xmlns="http://tempuri.org/">
<intA>5</intA>
<intB>7</intB>
</Add>
</soap:Body>
</soap:Envelope>'
The expected result is:
...
<AddResult>12</AddResult>
...
Use previous command defined, remove <intA>5</intA>
=> there is an error because the <intA>
tag has the minOccurs="1"
XSD property and Kong says:
HTTP/1.1 500 Internal Server Error
...
<faultstring>Request - XSD validation failed</faultstring>
<detail>Error Node: intB, Error code: 1871, Line: 5, Message: Element '{http://tempuri.org/}intB': This element is not expected. Expected is ( {http://tempuri.org/}intA ).<detail/>
Example (C1): Request | WSDL VALIDATION
: use a WSDL definition, which imports an XSD schema from the plugin configuration (no download)
Call incorrectly calculator
and detect issue in the Request with a WSDL definition. The XSD schema content is configured in the plugin itself and it isn't downloaded from an external entity.
-
'Reset' the configuration of
calculator
: remove thesoap-xml-request-handling
andsoap-xml-response-handling
plugins -
Add
soap-xml-request-handling
plugin tocalculator
and configure the plugin with:
VerboseRequest
enabledxsdApiSchema
property with thisWSDL
value:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="http://tempuri.org/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
name="Tempuri.org"
targetNamespace="http://tempuri.org/">
<wsdl:documentation>Tempuri.org - Add and Subtract calculation
</wsdl:documentation>
<wsdl:types>
<!-- XSD schema for the Request and the Response -->
<xsd:schema
xmlns:tns="http://schemas.xmlsoap.org/soap/envelope/"
targetNamespace="http://schemas.xmlsoap.org/soap/envelope/"
attributeFormDefault="qualified"
elementFormDefault="qualified">
<xsd:import namespace="http://tempuri.org/" schemaLocation="http://localhost:8000/tempuri.org.request-response.xsd"/>
</xsd:schema>
</wsdl:types>
</wsdl:definitions>
xsdApiSchemaInclude
property with this value:- key:
http://localhost:8000/tempuri.org.request-response.xsd
- value:
- key:
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" targetNamespace="http://tempuri.org/" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="Add" type="tem:AddType" xmlns:tem="http://tempuri.org/"/>
<xs:complexType name="AddType">
<xs:sequence>
<xs:element type="xs:integer" name="intA" minOccurs="1"/>
<xs:element type="xs:integer" name="intB" minOccurs="1"/>
</xs:sequence>
</xs:complexType>
<xs:element name="Subtract" type="tem:SubtractType" xmlns:tem="http://tempuri.org/"/>
<xs:complexType name="SubtractType">
<xs:sequence>
<xs:element type="xs:integer" name="intA" minOccurs="1"/>
<xs:element type="xs:integer" name="intB" minOccurs="1"/>
</xs:sequence>
</xs:complexType>
<xs:element name="AddResponse" type="tem:AddResponseType" xmlns:tem="http://tempuri.org/"/>
<xs:complexType name="AddResponseType">
<xs:sequence>
<xs:element type="xs:string" name="AddResult"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
- Note:
xsdApiSchemaInclude
is type ofmap
. You can add all theXSD
entries required. There is no limit of XSD files.
- Call the
calculator
through the Kong Gateway Route. Use command defined at step #6 of Example (B)
Example (C2): Request | WSDL VALIDATION
: use a WSDL definition, which imports an XSD schema from the plugin configuration (no download) for Kong Ingress Controller (KIC)
- If it’s not done yet, create the Kubernetes External Service and the related Ingress kind (see topic:
How to configure and test calculator Web Service in Kong Ingress Controller (KIC)
) - Create the Kubernetes
KongPlugin
ofsoap-xml-request-handling
. The yaml file (kic/kongPlugin-SOAP-XML-request.yaml) is already configured in regards ofexample #10-a
:wsdl
inxsdApiSchema
andXSD
import inxsdApiSchemaInclude
kubectl apply -f kic/kongPlugin-SOAP-XML-request.yaml
- Annotate the Ingress with
KongPlugin
kubectl annotate ingress calculator-ingress konghq.com/plugins=calculator-soap-xml-request-handling
- Call the
calculator
through the Kong Ingress. Use command defined at step #6 of Example (B). Replacelocalhost:8000
by thehostname:port
of the Kong gateway in Kurbenetes
See SAXON.md
- Request and Response |
XSLT 3.0 TRANSFORMATION
: JSON (client) to SOAP/XML (server): here - Request and Response |
XSLT 3.0 TRANSFORMATION
: XML (client) to JSON (server): here
Example (E): Request and Response | SOAP 1.2
XSD VALIDATION
: use a SOAP 1.2
XSD
definition and the calculator
API XSD
definition
Call correctly calculator
by using a SOAP 1.2
enveloppe. The SOAP 1.2
XSD imports http://www.w3.org/2001/xml.xsd
schema. This XSD schema content is configured in the plugin itself and it isn't downloaded from an external entity
-
'Reset' the configuration of
calculator
: remove thesoap-xml-request-handling
andsoap-xml-response-handling
plugins -
Add
soap-xml-request-handling
plugin tocalculator
and configure the plugin with:
VerboseRequest
enabledxsdSoapSchema
property: replace the default value by www.w3.org/2003/05/soap-envelope.xsdxsdSoapSchemaInclude
property with this value:- key:
http://www.w3.org/2001/xml.xsd
- value: see value in http://www.w3.org/2001/xml.xsd
- key:
xsdApiSchema
property with thisXSD
value:
<s:schema elementFormDefault="qualified" targetNamespace="http://tempuri.org/" xmlns:s="http://www.w3.org/2001/XMLSchema">
<s:element name="Add">
<s:complexType>
<s:sequence>
<s:element minOccurs="1" maxOccurs="1" name="intA" type="s:int" />
<s:element minOccurs="1" maxOccurs="1" name="intB" type="s:int" />
</s:sequence>
</s:complexType>
</s:element>
</s:schema>
- Add
soap-xml-response-handling
plugin tocalculator
and configure the plugin with:
VerboseResponse
enabledxsdSoapSchema
property: replace the default value by www.w3.org/2003/05/soap-envelope.xsdxsdSoapSchemaInclude
property with this value:- key:
http://www.w3.org/2001/xml.xsd
- value: see value in http://www.w3.org/2001/xml.xsd
- key:
xsdApiSchema
property with thisXSD
value:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" targetNamespace="http://tempuri.org/" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="AddResponse" type="tem:AddResponseType" xmlns:tem="http://tempuri.org/"/>
<xs:complexType name="AddResponseType">
<xs:sequence>
<xs:element type="xs:string" name="AddResult"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
- Call the
calculator
through the Kong Gateway Route
http POST http://localhost:8000/calculator \
Content-Type:'application/soap+xml; charset=utf-8' \
--raw '<?xml version="1.0" encoding="utf-8"?>
<soap12:Envelope xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
<soap12:Body>
<Add xmlns="http://tempuri.org/">
<intA>5</intA>
<intB>7</intB>
</Add>
</soap12:Body>
</soap12:Envelope>'
The expected result is:
...
<AddResult>12</AddResult>
...
Call correctly calculator
by setting the expected SOAPAction
Http header. The header name depends of the SOAP version:
- SOAP 1.1:
SOAPAction
Http header - SOAP 1.2:
action
inContent-Type
Http header
The WSDL v1.1 and WSDL v2.0 differ in how they define the SOAPAction
:
- WSDL 1.1:
soapAction
attribute - WSDL 2.0:
Action
attribute
-
'Reset' the configuration of
calculator
: remove thesoap-xml-request-handling
andsoap-xml-response-handling
plugins -
Change the URL of
calculator
Gateway Service: https://calculator.apim.eu:443/ws -
Add
soap-xml-request-handling
plugin tocalculator
and configure the plugin with:
SOAPAction_Header
property with the valueyes
VerboseRequest
enabledxsdApiSchema
property with thisWSDL 1.1
value: dneonline.com.wsdl (v1.1)
- Call the
calculator
through the Kong Gateway Route. As theÀdd
operation name is requested (seesoapActionRequired="true"
in WSDL), theSOAPAction
has thehttp://tempuri.org/Add
value as defined in the WSDL
http POST http://localhost:8000/calculator \
Content-Type:'text/xml; charset=utf-8' \
SOAPAction:"http://tempuri.org/Add" \
--raw '<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<Add xmlns="http://tempuri.org/">
<intA>5</intA>
<intB>7</intB>
</Add>
</soap:Body>
</soap:Envelope>'
The expected result is:
...
<AddResult>12</AddResult>
...
- If the
SOAPAction
is not set correctly regarding theWSDL
, the plugin detects it and sends an error message
- Use previous command defined, remove
SOAPAction
and Kong says:
HTTP/1.1 500 Internal Server Error
...
<faultstring>Request - XSD validation failed</faultstring>
<detail>Validation of 'SOAPAction' header: The 'SOAPAction' header is not set but according to the WSDL this value is 'Required'</detail>
- Use previous command defined, set
SOAPAction:"http://tempuri.org/Subtract"
and Kong says:
HTTP/1.1 500 Internal Server Error
...
<faultstring>Request - XSD validation failed</faultstring>
<detail>Validation of 'SOAPAction' header: The Operation Name found in 'soap:Body' is 'Add'. According to the WSDL the 'SOAPAction' should be 'http://tempuri.org/Add' and not 'http://tempuri.org/Subtract'</detail>
- If the
SOAPAction
is not set but there issoapActionRequired="false"
(in the WSDL) forSubtract
operation, the plugin allows the request
http POST http://localhost:8000/calculator \
Content-Type:'text/xml; charset=utf-8' \
--raw '<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<Subtract xmlns="http://tempuri.org/">
<intA>5</intA>
<intB>7</intB>
</Subtract>
</soap:Body>
</soap:Envelope>'
The expected result is:
...
<SubtractResult>-2</SubtractResult>
...
-
'Reset' the configuration of
calculator
: remove thesoap-xml-request-handling
andsoap-xml-response-handling
plugins -
Change the URL of
calculator
GW Service: https://calculator.apim.eu:443/ws -
Add
soap-xml-request-handling
plugin tocalculator
and configure the plugin with:
SOAPAction_Header
property with the valueyes
VerboseRequest
enabledxsdApiSchema
property with thisWSDL 1.1
value: dneonline.com.wsdl (v1.1)xsdSoapSchema
property: replace the default value by www.w3.org/2003/05/soap-envelope.xsdxsdSoapSchemaInclude
property with this value:- key:
http://www.w3.org/2001/xml.xsd
- value: see value in http://www.w3.org/2001/xml.xsd
- key:
- Call the
calculator
through the Kong Gateway Route. As theÀdd
operation name is requested (seesoapActionRequired="true"
in WSDL), theaction
has thehttp://tempuri.org/Add
value as defined in the WSDL
http POST http://localhost:8000/calculator \
Content-Type:'application/soap+xml; charset=utf-8; action="http://tempuri.org/Add"' \
--raw '<?xml version="1.0" encoding="utf-8"?>
<soap12:Envelope xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
<soap12:Body>
<Add xmlns="http://tempuri.org/">
<intA>5</intA>
<intB>7</intB>
</Add>
</soap12:Body>
</soap12:Envelope>'
The expected result is:
...
<AddResult>12</AddResult>
...
Follow the steps defined for WSDL 1.1 | SOAP 1.1 and specifically configure the plugin with:
xsdApiSchema
property with thisWSDL 2.0
value: dneonline.com.wsdl (v2.0)
Call the Add
operation with a SOAP 1.1 envelope and SOAPAction:"http://tempuri.org/Add"
as there is a defined value for the Action
attribute
Call the Subtract
operation with a SOAP 1.1 envelope and SOAPAction:"http://tempuri.org/SubtractInterface/SubtractRequest"
as there is not defined value for the Action
attribute. So the default action pattern is used as defined by the W3C
Follow the steps defined for WSDL 1.1 | SOAP 1.2 and specifically configure the plugin with:
xsdApiSchema
property with thisWSDL 2.0
value: dneonline.com.wsdl (v2.0)
Call the Add
operation with a SOAP 1.2 envelope and Content-Type:'application/soap+xml; charset=utf-8; action="http://tempuri.org/Add"'
as there is a defined value for the Action
attribute
Call the Subtract
operation with a SOAP 1.2 envelope Content-Type:'application/soap+xml; charset=utf-8; action="http://tempuri.org/SubtractInterface/SubtractRequest"'
as there is not defined value for the Action
attribute. So the default action pattern is used as defined by the W3C
Example (G): Request | XSLT TRANSFORMATION
with Parameters applied by the libxslt
(or saxon
) library
The plugin applies an XSLT Transformation on XML request by using <xsl:param>
defined in the plugin config
. The transformations are:
<intA>
value transformed to1111
<intB>
value transformed to3333
<Username>
value transformed toKongUser
referenced in a Vault{vault://env/soap-username}
<Password>
value transformed toKongP@sswOrd!
referenced in a Vault{vault://env/soap-password}
- Add the following environment variables at the Kong Linux level, for instance for a Docker deployment (see start-kong.sh):
-e "SOAP_USERNAME=KongUser" \
-e "SOAP_PASSWORD=KongP@sswOrd!" \
-e "KONG_LOG_LEVEL=debug" \
Restart the Kong node and pay attention to the KONG_LOG_LEVEL=debug
as it will be useful later
- Create 2 x Vault environment variables
- Go on
Vaults
- Create the 1st Vault with:
Environment Variables
selectedEnvironment Variable Prefix
withenv
valuePrefix
withsoap-username
value
- Create the 2nd Vault with:
Environment Variables
selectedEnvironment Variable Prefix
withenv
valuePrefix
withsoap-password
value
- 'Reset' the configuration of
calculator
: remove thesoap-xml-request-handling
andsoap-xml-response-handling
plugins - Add
soap-xml-request-handling
plugin tocalculator
and configure the plugin with:
VerboseRequest
enabledxsltLibrary
property withlibxslt
orsaxon
valuexsltTransformBefore
property with this XSLT definition:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:param name="intA_param" select="1"/>
<xsl:param name="intB_param" select="2"/>
<xsl:param name="SOAP_USERNAME" select="MyUser"/>
<xsl:param name="SOAP_PASSWORD" select="MyPassword"/>
<xsl:output version="1.0" method="xml" encoding="utf-8" omit-xml-declaration="no"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="//*[local-name()='Username']">
<Username><xsl:value-of select="$SOAP_USERNAME"/></Username>
</xsl:template>
<xsl:template match="//*[local-name()='Password']">
<Password><xsl:value-of select="$SOAP_PASSWORD"/></Password>
</xsl:template>
<xsl:template match="//*[local-name()='intA']">
<intA><xsl:value-of select="$intA_param"/></intA>
</xsl:template>
<xsl:template match="//*[local-name()='intB']">
<intB><xsl:value-of select="$intB_param"/></intB>
</xsl:template>
</xsl:stylesheet>
XsltParams
property with these values:- key:
intA_param
- value:
1111
- key:
intB_param
- value:
3333
- key:
SOAP_USERNAME
- value:
{vault://env/soap-username}
- key:
SOAP_PASSWORD
- value:
{vault://env/soap-password}
- key:
- Call the
calculator
through the Kong Gateway Route
http POST http://localhost:8000/calculator \
Content-Type:'text/xml; charset=utf-8' \
--raw '<?xml version="1.0" encoding="utf-8"?>
<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header xmlns:auth="http://wwww.example.com">
<auth:Authentication xmlns:auth="http://example.com/auth">
<Username>**TO_BE_CHANGED**</Username>
<Password>**TO_BE_CHANGED**</Password>
</auth:Authentication>
</soapenv:Header>
<soapenv:Body>
<Add xmlns="http://tempuri.org/">
<intA>5</intA>
<intB>7</intB>
</Add>
</soapenv:Body>
</soapenv:Envelope>'
The expected result is no longer 12
but 4444
:
...
<AddResult>4444</AddResult>
...
As the calculator
service doesn't check the <Username>
and <Password>
values open the Kong Log and look for XSLT transformation, END
debug and see the transformation applied by using the Vault referenced values.
The expected result is:
<Username>
value is transformed toKongUser
referenced in the Vault<Password>
value is transformed toKongP@sswOrd!
referenced in the Vault
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Header xmlns:auth="http://wwww.example.com">
<auth:Authentication xmlns:auth="http://example.com/auth">
<Username>KongUser</Username>
<Password>KongP@sswOrd!</Password>
</auth:Authentication>
</soapenv:Header>
<soapenv:Body>
<Add xmlns="http://tempuri.org/">
<intA>1111</intA>
<intB>3333</intB>
</Add>
</soapenv:Body>
</soapenv:Envelope>
SOAP/XML | Plugin | libxml2 | libxlt | saxon HE | W3C URL | Comment |
---|---|---|---|---|---|---|
SOAP 1.1 Envelope | All (except for plugin features not supported by the library) | ✅ | ✅ | ✅ | http://schemas.xmlsoap.org/soap/envelope/ | The Content-Type is text/xml for SOAP 1.1 |
SOAP 1.2 Envelope | All (except for plugin features not supported by the library) | ✅ | ✅ | ✅ | http://www.w3.org/2003/05/soap-envelope | The Content-Type is application/soap+xml for SOAP 1.2 |
XSLT 1.0 | XSLT TRANSFORMATION |
N/A | ✅ | ✅ | http://www.w3.org/1999/XSL/Transform | See version=1.0 attribute in XSLT |
XSLT 2.0/3.0 | XSLT TRANSFORMATION |
N/A | ❌ | ✅ | http://www.w3.org/1999/XSL/Transform | See version=2.0 or version=3.0 attribute in XSLT |
Schema XML 1.0 | WSDL/XSD VALIDATION |
✅ | N/A | ⬛ | http://www.w3.org/2001/XMLSchema | |
WSDL 1.1 | WSDL/XSD VALIDATION |
✅ | N/A | ⬛ | http://schemas.xmlsoap.org/wsdl/ | See <definitions> in WSDL 1.0 |
WSDL 2.0 | WSDL/XSD VALIDATION |
✅ | N/A | ⬛ | http://www.w3.org/ns/wsdl | See <description> in WSDL 2.0 |
SOAPAction | WSDL/XSD VALIDATION |
✅ | N/A | ⬛ | http://schemas.xmlsoap.org/wsdl/ (WSDL 1.1) and http://www.w3.org/ns/wsdl (WSDL 2.0) | SOAPAction Http header for SOAP 1.1 and action in Content-Type Http header for SOAP 1.2 |
XPath 1.0 | ROUTING BY XPATH |
✅ | N/A | ⬛ | https://www.w3.org/TR/xpath-10/ |
- Table legend
- ✅: supported by the library
- ❌: not supported by the library
- ⬛: supported by the library but not available due to license restiction (it only concerns
saxon HE
that stands for Home Edition) - N/A: not applicable
- Libraries availability
- The
libxml2
andlibxlt
libraries are already included in kong/kong-gateway Enterprise Edition Docker image - The
saxon HE
library is not included in the Kong Docker image, see SAXON.md for how to integrate saxon with Kong
The functional testing is available through pongo
- Download
pongo
- Initialize
pongo
- Run tests with pongo.sh and adapt the
KONG_IMAGE
value according to expectations
Note: If the Kong Docker image with saxon
has been rebuilt, run a pongo clean
for rebuilding the Pongo image
The Load testing benchmark is performed with K6. See LOADTESTING.md
- The
soap-xml-response-handling
plugin doesn't work for HTTP/2
- It's due to the current Nginx limitation. See Kong Gateway doc
- The
WSDL/XSD VALIDATION
has following limitations:
- If the WSDL/XSD schema imports an XSD from external entity, it uses a callback function (i.e.
libxml2ex.xmlMyExternalEntityLoader
called bylibxml2
). As it's a non-yield function it must use thesocket.http
(blocking library). To avoid this limitation please:- Have at least 2 Nginx worker processes or enable the experimental
ExternalEntityLoader_Async
property (which usesresty.http
) or - Use
config.xsdApiSchemaInclude
andconfig.xsdSoapSchemaInclude
- Have at least 2 Nginx worker processes or enable the experimental
- If
stream_listen
is enabled, thekong.ctx.shared
is not set correctly inlibxml2ex.xmlMyExternalEntityLoader
. It impacts the WSDL/XSD validation which can perform imports: theconfig.xsdApiSchemaInclude
,config.xsdSoapSchemaInclude
andconfig.ExternalEntityLoader_Async
are ignored; and theimport
is only done throughsocket.http
(blocking library). The recommendation is to disablestream_listen
with the SOAP/XML plugins and have a dedicated Kong GW that enablesstream_listen
- The Asynchronous download of the XSD schemas (with
config.ExternalEntityLoader_Async
) uses a LRU cache (Least Recently Used) for storing the content of XSD schema. The default size is2000
entries. When the limit has been reached there is a warning message in the Kong log
WSDL/XSD VALIDATION
applies for SOAP 1.1 or SOAP 1.2 but not both simultaneously
- It's related to
config.xsdSoapSchema
andconfig.xsdSoapSchemaInclude
. To avoid this limitation please create one Kong route per SOAP version
- The MIME type of the request's
Content-Type
is not checked by the plugin
- For the record
Content-Type
of SOAP 1.1 istext/xml
andContent-Type
of SOAP 1.2 isapplication/soap+xml
. In case of error the plugins send back to the consumer a genericContent-Type
:text/xml; charset=utf-8
regardless of the SOAP version
- v1.0.0:
- Initial Release
- v1.0.1:
- Improved the behavior of SOAP/XML Handling plugins in conjunction with the Kong System plugins: Rate Limiting, Auth (OIDC, basic-auth, etc.)
- Reformated the JSON Error messages (of Kong System plugins) to a SOAP/XML
<soap:Fault>
error
- v1.0.2:
- Added the capacity to provide
wsdl
content toxsdApiSchema
. The raw<xs:schema>
is still valid
- Added the capacity to provide
- v1.0.3:
- When
VerboseRequest
orVerboseResponse
are disabled, the plugins no longer send the detailed error to the logs
- When
- v1.0.4:
- Improved the log error management by initializing it in the
init_worker
phase
- Improved the log error management by initializing it in the
- v1.0.5:
- Added an external loader (http)
- v1.0.6:
- Added
Timeout
andCache_TTL
parameters related to the External Entity Loader (http(s)) - Put the detailed error message in
<detail>
of<soap:Fault>
message in caseVerboseRequest
orVerboseResponse
is enabled - Adapted the
schema.lua
to be Konnect compatible
- Added
- v1.0.7:
- Changed example material from
https://ecs.syr.edu
(no longer available) tohttp://www.dneonline.com
- Improved
Routing By XPath
by putting in one plugin property the complete routing URL and by enabling the usage of a Host (not only a Kong Upstream) - Added experimental
ExternalEntityLoader_Async
capacity for downloading Asynchronously the XSD External Entities
- Changed example material from
- v1.0.8:
- Added https support to Synchronous external loader (https)
WSDL validation
: Get the Namespace definitons found in<wsdl:definitions>
and add them in<xsd:schema>
(if they don't exist)
- v1.0.9:
- In case of
request-termination
plugin there is no longer SOAP/XML - 200 error xsdApiSchemaInclude
: support the inclusion of multiple XSD schemas in the plugin configuration (without download external entity)- Enhanced the documentation for Kubernetes, Konnect and KIC
- In case of
- v1.0.10:
- Due to Kong v3.6+, updated the Kong's library used for gzip compression (from
kong.tools.utils
tokong.tools.gzip
)
- Due to Kong v3.6+, updated the Kong's library used for gzip compression (from
- v1.0.11:
- Added
pongo
tests
- Added
- v1.1.0:
- Added
saxon
Home Edition (v12.5) library for supporting XSLT 2.0 or 3.0 - Fixed a free memory issue for
libxslt
(and avoid[alert] 1#0: worker process **** exited on signal 11
error during Nginx shutdown) - Added an
Error Handler
forlibxslt
to detect correctly the unsupported XLST 2.0 or 3.0 - Added
jit.off()
forlibxml
to avoidnginx: lua atpanic: Lua VM crashed, reason: bad callback
error
- Added
- v1.1.1:
- Added the
saxon
notices files (related to the Saxon license distribution) - Added support for
XML
toJSON
transformation - Renamed the
kong-saxon-initcontainer
andkong-saxon
docker images
- Added the
- v1.1.2:
saxon
library: removed thexsltSaxonTemplate
andxsltSaxonTemplateParam
parameters and useXSLT
without<xsl:template name="main">
- Added
conf/saxonConf.xml
forsaxon
configuration file - Added nginx
pid
forsaxon
logs
- v1.1.3:
- Loaded
saxon
library during theconfigure
nginx phase only if necessary
- Loaded
- v1.1.4:
ExternalEntityLoader_Async
: replacednginx.timer.at
bykong.tools.queue
- v1.1.5:
- Removed the
require("kong.plugins.soap-xml-handling-lib.xmlgeneral")
declared on each phase to a global definition ExternalEntityLoader_Async
: replace thekong.xmlSoapAsync.entityLoader.urls
to a LRU cache- Replaced
plugin.PRIORITY
byplugin.__plugin_id
regarding the Error management
- Removed the
- v1.1.6:
ExternalEntityLoader_Async
: used akong.tools.queue
to execute a WSDL/XSD validation prefetch on theconfigure
nginx phase (for downloading theìmport
ed XSD)
- v1.2.0:
- Improved support for
SOAP
v1.1 and v1.2, which does anìmport
(that can be included in a new property:xsdSoapSchemaInclude
) - Added the validation of the
SOAPAction
Http header xmlgeneral.pluginConfigure
: enabled theXSD_Validation_Prefetch
forsaxon
library (not onlylibxslt
)- Added a
Known Limitations
section in the README.md - If
stream_listen
is enabled, send an error message in the log and forces the synchronous download by usingsocket.http
(blocking library)
- Improved support for
- v1.2.1
- Added a table of contents in the README.md
- Added support of
WSDL
2.0 (forWSDL/XSD Validation
) WSDL/XSD Validation
: Handle correctly the case where the Namespace (associated withhttp://www.w3.org/ns/wsdl
orhttp://www.w3.org/2001/XMLSchema
) has no prefixxmlgeneral.addNamespaces
: fixed a memory issue when the prefix is NULL (example:xmlns="http://www.w3.org/ns/wsdl"
instead ofxmlns:wsdl="http://www.w3.org/ns/wsdl"
)- Send the correct detailed error message (instead
Ko
) in case there is no Operation in<soap:Body>
- Optimized the
WSDL
validation (in case of multiple<xs:schema>
): match the Operation in<soap:Body>
with its associated<xs:element name=
in<xs:schema>
- Have a dynamic loading of the Kong's library used for gzip compression regarding the Kong version:
kong.tools.utils
for version < 3.6 andkong.tools.gzip
for version >= 3.6 - Replaced the usage of
https://ecs.syr.edu
by a local calculator - Included the Kong version in the docker image related to
saxon
(example:jeromeguillaume/kong-saxon:3.8.1.0-1.2.1-12.5
) - Included the Lua code SOAP/XML plugins in the docker images related to
saxon
- Pongo (Tests): removed the external dependencies (from
http://www.dneonline.com:80/calculator.asmx
tojeromeguillaume/ws-soap-calculator
Docker image and fromhttp://httpbin.apim.eu
tosvenwal/httpbin
Docker image)
- v1.2.2
saxon
-XSLT Transformation
: removed empty Namespace (example:xmlns=""
)XSLT Transformation
: Improved error message in case XSLT definition or XML input is not correctWSDL/XSD Validation
: Improved error message in case WSDL/XSD schema or XML input is not correctWSDL/XSD Validation
: Improved the validation mechanism in case of multiple schemas to have a better match between the XML ad its WSDL/XSD schema (by leveraging the error code1845
-No matching global declaration available for the validation root
onxmlSchemaValidateOneElement
call)soap-xml-response-handling
: removed the call ofxmlgeneral.sleepForPrefetchEnd
due tongx.sleep
that is not allowed inheader
phase
- v1.2.3
- Validation of
SOAPAction
Http header: fixed the header name detection for SOAP 1.2 (fromSOAPAction
toaction
inContent-Type
) - Validation of
SOAPAction
Http header: handled the default namespace forsoap
,soap12
,wsdl
(example:xmlns="http://www.w3.org/ns/wsdl"
instead ofxmlns:wsdl="http://www.w3.org/ns/wsdl"
)
- Validation of
- v1.2.4
- Validation of
SOAPAction
Http header: added WSDL 2.0 support - Added the Lua code checking that the pointer passed to
ffi.string
is notffi.NULL
(and avoid a crash:[alert] 1#0: worker process XXXX exited on signal 11
) - Added a
W3C Compatibility Matrix
section in the README.md pongo
tests: removedit()
fromlazy_setup()
and removedteardown()
and puthelpers.stop_kong()
inlazy_teardown()
- Validation of
- v1.2.5
- Fixed a memory leak in XSLT Transformation due to the
libxslt
taking ownership of the pointer returned byxmlReadMemory
(see comments inlibxml2ex.lua
forxmlReadMemory
) - Added Load testing benchmark. See LOADTESTING.md
- Fixed a memory leak in XSLT Transformation due to the
- v1.2.6
- Added
xsltParams
: named parameter (<xsl:param>
) to use inXSLT Transformation
- Added
- v1.2.7
- Added
pongo
tests forxsltParams
- Added the detection of non existing symbols in
libsaxon4kong.lua
- Added