[wso2][APIM 3.2] conditional engagement of handler does not work

Viewed 55

I try to write my own WSO2 3.2 APIM Handler.

My purpose is :

  • engage Handler when a dedicated property is set on API
  • consume the request and use the binary response to decrypt part of it
  • change the content type of the response after decryption

I successfuly write my handler and modify the velocity_template.xml as follow (following the documentation):

#if($apiObj.additionalProperties.get('encrypted') == "true"))
<handler class="org.rudi.wso2.mediation.EncryptedMediaHandler">
    <property name="encryptedMimeType" value="$apiObj.additionalProperties.get('encrypted_mime_type')"/>
    <property name="mimeType" value="$apiObj.additionalProperties.get('mime_type')"/>
    <property name="providerUuid" value="dummy"/>
</handler>
#end

But this does not work and the handler is not engaged.

If I remove the #if condition the handler is engaged but the properties are not interpreted (for exemple the "mimeType" field is explicitly set to "$apiObj.additionalProperties.get('mime_type')" and not to the value of the additionnalProperty set on API.

What is wrong ? How could I use the additionnal properties added on API ?

Next when the Handler is called, I did not find any way to read the response of the endpoint.

I find code to change the response ou the response status code to write fault for exemple

But I did not find a way to read the binary response send by my endpoint to work on it.

Help will be appreciated!

UPDATED

For the second part of the question, I create a method as follow:

private void replaceBody(SOAPBody body) throws IOException {
        OMElement element = body.getFirstElement();
        if (element.getLocalName().equalsIgnoreCase(BINARY_LOCAL_NAME)) {
            OMNode subChild = element.getFirstOMChild();
            if (subChild instanceof OMText && ((OMText) subChild).isBinary()) {
                OMText textNode = ((OMText) subChild);
                DataHandler originalDataHandler = (DataHandler) textNode.getDataHandler();

                InputStream modifiedInputStream = modify(originalDataHandler.getInputStream());

                DataHandler newDataHandler = new DataHandler(new StreamingOnRequestDataSource(modifiedInputStream ));
                OMText newTextNode = body.getOMFactory().createOMText(newDataHandler, true);

                textNode.insertSiblingBefore(newTextNode);
                textNode.detach();
            }
        }
    }

And I lookup for SOAPBody as follow :

org.apache.axis2.context.MessageContext axis2MC = ((Axis2MessageContext) messageContext)
                    .getAxis2MessageContext();
RelayUtils.buildMessage(axis2MC, true);
axis2MC.setProperty(RelayConstants.FORCE_RESPONSE_EARLY_BUILD, Boolean.TRUE);
SOAPBody body = axis2MC.getEnvelope().getBody();

I test the behaviour on small file but I think we need to do more stuff to handle big file ou chunked api.

Any advice?

1 Answers

Regarding velocity_template.xml & API Properties Configurations

The velocity_template.xml file is used to construct the API Synapse Artifacts to deploy them in the Gateway. As it is a common template file, you have to place your conditions and customizations in the correct sections of the template to reflect in the Synapse Artifact.

If you are trying to publish a REST API, then place your code block after this section in the velocity_template.xml

#foreach($handler in $handlers)
<handler xmlns="http://ws.apache.org/ns/synapse" class="$handler.className">
    #if($handler.hasProperties())
    #set ($map = $handler.getProperties() )
    #foreach($property in $map.entrySet())
    <property name="$!property.key" value="$!property.value"/>
    #end
    #end
</handler>
#end

<!-- place your block here -->

This makes sure, that your handler is engaged after all mandatory Handlers of the API Managers are engaged. If you want to engage your handler in the middle, then add a condition within #foreach block to append your handler. You can follow this doc for more detailed information.

Once the velocity_template.xml changes are made, re-publish the API by selecting the Gateway environments to deploy the updated Synapse Artifacts. If it is a distributed environment, make sure to update the velocity_template.xml of the Publisher node.

Also, check for any typos in your code block: I see an extra ) at the end of the #if condition.

#if($apiObj.additionalProperties.get('encrypted') == "true"))
...
Related