WSO2 ESB (Apache Synapse) Proxy with response processing

949 Views Asked by At

me again. As a technical exercise I'm attempting to use WSO2 ESB to proxy some web traffic. Specifically, I'm attempting to proxy web traffic and alter the returned response on-the-fly like so:

  • Have ESB receive a HTTP request
  • proxy the request to a specific server
  • receive the response
  • find any occurrence of the word "sad" and replace it with "happy" (case insensitive regex)
  • pass the altered response back to the browser

One would think this is a simple regex or XSLT operation but this is turning out to be much harder than I thought. For the moment, this is the proxy script I am using...

<?xml version="1.0" encoding="UTF-8"?>
<proxy xmlns="http://ws.apache.org/ns/synapse"
       name="PassProxy"
       transports="https http"
       startOnLoad="true"
       trace="disable">
   <description>Route content from a web server through the ESB service and alter it</description>
   <target>
      <endpoint>
         <address uri="http://server.yoyodyne.com/"/>
      </endpoint>
      <inSequence/>
      <outSequence>
         <property name="TheContentIncludingTheSoapEnvelope" expression="."/>
         <property xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
                   xmlns:ns="http://org.apache.synapse/xsd"
                   name="TheContentFromSoapBodyButNotReally"
                   expression="//soapenv:Envelope/soapenv:Body/*"/>
         <property name="TheContent"
                   value="An initial value that should be replaced"
                   scope="default"
                   type="STRING"/>
         <enrich>
            <source type="body" clone="true"/>
            <target type="property" property="TheContent"/>
         </enrich>
         <property name="ContentType" expression="$trp:Content-Type"/>
         <property name="ContentLength" expression="$trp:Content-Length"/>
         <log level="custom">
            <property name="ContentType" expression="$trp:Content-Type"/>
            <property name="ContentLength" expression="$trp:Content-Length"/>
            <property name="MessageVar" value="TheContent"/>
            <property name="TargetMessage" expression="get-property('TheContent')"/>
         </log>
         <script language="js">
            //hack because xpath fn:replace does not work in property tags and fn:translate works on chars not whole strings
            var contentType=mc.getProperty('ContentType');
            var contentObject=mc.getProperty('TheContent'); //how to get the text of this? And do it in un-escaped format???
            if(/text/i.test(contentType)) {
                if(!contentObject) {
                    mc.setProperty('TheAlteredContent','Well that didn\'t work as expected');
                } else {
                    if(typeof contentObject == 'object' || typeof contentObject == 'undefined') {
                        var returnMessage='';
                        for (var key in contentObject) {
                            returnMessage=returnMessage+'found key "'+key+'"\n';
                        } //end object key for
                        returnMessage='Can\'t work with this type of input - '+typeof contentObject+'n\Available keys to try:\n'+returnMessage;
                        contentObject=returnMessage;
                    } else {
                        contentObject=contentObject.replaceAll('sad', 'happy');
                        //more regex statements to go here
                    } //end typeof if
                } //end property check if
            } else {
                //not text - do nothing
                contentObject='binary content (I think). Found content type of "'+contentType+'"';
            } //end content type check if
            //send the content back
            mc.setProperty('TheAlteredContent',contentObject);
         </script>
         <enrich>
            <!-- need to figure out how to replace the content and not append to the end of it. Replace tag on target keeps getting removed for some reason -->
            <source type="property" property="TheAlteredContent" clone="true"/>
            <target type="body"/>
         </enrich>
         <!-- doctype headers in the HTML cause logging to fail, so no debugging for you -->
         <!--<log level="full"/>-->
         <send/>
      </outSequence>
   </target>
</proxy>

Granted using enrich operations is probably not the best way to handle this, but it seemed like a good idea at the time. What ends up happening is that the HTML portion of the response gets passed into the JS code as an object with escaped content (or gets passed out???). Because the "contentObject" var is an object the regex fails. Forcing "contentObject" to a string using toString() also does not work. Even if it did work, The HTML content is still in an escaped form and conversion back could be problematic given that there may have been escaped entries in the HTML code that may need to stay in HTML format. The final problem here is that the content of the property of "TheAlteredContent" is being appended to the content and not replacing it, even when the attribute "action=replace" is added to the final enrich operation (the ESB actually removes it).

Anyone know how a better way to do this, or perhaps a way to make the above code work?

1

There are 1 best solutions below

1
On

I believe that, you are receiving HTML response from the backend. Simply use a custom class mediator in the outpath and change the content. I mean, do a String.replace in the mediate() code. It would be fairly simple than making whole complex coding logic in a proxy configuration using a javascript..

Will that solve your issue?