could have been titled "Processing binary data in DataPower stylesheets 1/x".
This posting is the second of several postings on processing of binary data in DataPower stylesheets.
Again this is on CDATA as in the postings "CDATA .../x".
This time the (customer) problem was as follows:
- accept XML input data
- do XML threat protection
- if no threat, pass input unmodified to backend (preserve any CDATA elements).
While preserving of CDATA might be done with cdata-section-elements of <xsl:output ... /> you have to know which elements you want to have CDATA output for,
In case of DataPowwer as generic proxy any element might contain CDATA section or might not contain CDATA sections.
If the service would have XML request type CDATA sections are gone -- therefore we need a Non-XML service.
But XML threat protection does not work in Non-XML service -- therefore we need a second XML service.
Now lets discuss the solution I came up with.
Setup XML-FW with XML request type with its own XML Manager and any specific XML Parser settings.
(I did set "XML Element Depth" to 1, service is on port 2060)
Setup XML-FW with Non-XML request type, and these two actions:
1) binary transform action from INPUT to NULL with stylesheet check.xsl
2) results action from INPUT to OUTPUT
This is the binary transform stylesheet check.xsl I used.
<dp:input-mapping href="store:///pkcs7-convert-input.ffd" type="ffd"/>
<xsl:if test="$response/url-open/responsecode != 200">
The <dp:input-mapping ... /> uses Flat File Descriptor (FFD) store:///pkcs7-convert-input.ffd shipped with DataPower and used by five PKCS7 stylesheets located in store:/// folder.
As documented in the FFD itself (see below) it generates structure <object><message>***binary data***</message></object> with a binaryNode as child of <message> element.
Find the details on binaryNode in previous posting.
Now the "binary data" (which in this case is XML data, but we want pass it unmodified) needs to be posted to second XML (threat protection) service by <dp:url-open>.
Posting binary data with <dp:url-open> is done with data-type="base64".
Therefore we just convert the binaryNode data to base64 by dp:binary-encode(/object/message) in <dp:url-open>.
We are not interested in the response of the service called but only in its response code, therefore response="responsecode".
The result of <dp:url-open> call is stored in variable $reponse.
In case the HTTP response code is not equal to 200 we know that something is wrong, and for the service called we know that XML threat protection found a problem.
Therefore we abort service execution by <dp:reject>.
So if service execution does not get aborted by <dp:reject> the results action from INPUT to OUTPUT just copies the unmodified INPUT to OUTPUT (preserving any CDATA section).
Otherwise (in case of a detected XML threat) the service returns a generic error message to the client.
What we have seen is
- how to process binary (Non-XML) input data (resulting in a binaryNode)
- how to convert a binaryNode to a base64 encoded string
- how to pass "binary" data to dp:url-open() by data-type="base64"
- how to process response code of dp:url-open
By the arguments above there cannot be a solution without a side call.
And this is from stylesheet "store:///pkcs7-convert-input.ffd":
This FFD converts the input into an XML tree like this: