IC5Notice: We have upgraded developerWorks Community to the latest version of IBM Connections. For more information, read our upgrade FAQ.
Topic
  • 2 replies
  • Latest Post - ‏2014-07-01T10:19:38Z by HermannSW
JoeMorganNTST
JoeMorganNTST
427 Posts

Pinned topic Gotta Love GatewayScript and V7

‏2014-06-30T20:31:07Z |

We are all upgraded to V7 and started working on a back-log of GatewayScript to handle things.  Our first, and one of the more painful things to do in XSLT is a simple search and replace.   Here is a highly reusable GatewayScript that will do just that for any string input:

var hm = require('header-metadata');

var jsName = 'SearchAndReplace.js';
var sourceString = session.parameters.sourceString;
var targetString = session.parameters.targetString;

console.debug('%s - Source String: %s', jsName, sourceString);
console.debug('%s - Target String: %s', jsName, targetString);

try {
    var request = session.input.readAsBuffer(function(readAsBufferError, xmlData) {
                if (readAsBufferError) {
                        console.error('%s - %s: %s', jsName, 'Read as Buffer Error', readAsBufferError);
                        session.output.write('readAsBuffer:' + readAsBufferError);
                }
                else {
                        var responseXML = replaceAll(xmlData.toString(), sourceString, targetString);
//                      console.debug('%s - Result String: %s', jsName, responseXML);

                        hm.current.set('Content-Type', 'text/xml');
                        session.output.write(responseXML);
                }
        });
}
catch(err) {
        console.error('%s - %s: %s', jsName, 'Read as Buffer Error', err.message);
        session.output.write('readAsBuffer: ' + err.message);
}

function replaceAll(str, source, target) {
//      console.debug('%s - replaceAll - IncomingString is:  %s', jsName, str);
        console.debug('%s - replaceAll - source:  %s', jsName, source);
        console.debug('%s - replaceAll - target:  %s', jsName, target);

        return str.replace(new RegExp(source, 'g'), target);
}



Note it has parameters, so you'll need to be sure to add the two parameters under the "Advanced" tab making sure they are named "sourceString" and "targetString".

Lots of debugging output and hopefully easy to understand.  I've already identified a few enhancements to make to this such as adding parameters to identify if the S/R operation should work on the payload or headers, and also enabling the source string and/or target string to be hard-coded (as is in this example) or come from variables, or from somewhere else.   You may have other ideas.

Enjoy!!!!

Thanks IBM and the DataPower group.  Life is better!
 

  • HermannSW
    HermannSW
    4524 Posts

    Re: Gotta Love GatewayScript and V7

    ‏2014-07-01T10:19:08Z  

    Hi Joe,

    > We are all upgraded to V7 and started working on a back-log of GatewayScript to handle things. 
    >
    it is good to see your excitement on GatewayScript.


    > Our first, and one of the more painful things to do in XSLT is a simple search and replace.  
    > Here is a highly reusable GatewayScript that will do just that for any string input:
    >
    At least your variable name "xmlData" seems to indicate that you might want to replace strings in XML data by just regexp:replace() and treating XML as just a string. There are a few issues with this:

    • if sourceString is just '>' you will break XML
    • you cannot handle XML because the encoding of stylesheet parameters "sourceString" and "targetString" is UTF-8 and your GatewayScript script only handles UTF-8 encoded (string) input
    • you cannot even make sure input is XML (see attached service export, request type is XML but that does NOT ensure XML input)
    • in general, as long as GatewayScript does not ship XML(crypto) modules XML(crypto) processing should not be done by GatewayScript


    In attached service you will find your script at endpoint "/js", the equivalent XSLT+FFD under "/ffd" and finally XSLT based on shipped FFD under "/shipped" (that does UTF-8 validation of input string in addition).

    Here you see that all do same replacement of German umlaut 'ä' by its (German) equivalent term 'ae', and that GatewayScript cannot handle ISO-8859-1 encoded input string ('ä' is 0xE4 there):

    $ echo -e "1ä2" | curl --data-binary @- http://dp2-l3:5201/js
    1ae2
    $ echo -e "1ä2" | curl --data-binary @- http://dp2-l3:5201/ffd
    1ae2
    $ echo -e "1ä2" | curl --data-binary @- http://dp2-l3:5201/shipped
    1ae2
    $ 
    $ echo -e "1\xC3\xA42" | curl --data-binary @- http://dp2-l3:5201/js
    1ae2
    $ echo -e "1\xC3\xA42" | curl --data-binary @- http://dp2-l3:5201/ffd
    1ae2
    $ echo -e "1\xC3\xA42" | curl --data-binary @- http://dp2-l3:5201/shipped
    1ae2
    $ 
    $ echo -e "1\xE42" | curl --data-binary @- http://dp2-l3:5201/js
    1�2
    $
    

     

    > Our first, and one of the more painful things to do in XSLT is a simple search and replace. 
    >
    Again, from my point of view the XSLTs are definitely not more complicated than your script, perhaps even simpler.

    replace.xsl:

    <xsl:stylesheet version="1.0"
      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
      xmlns:regexp="http://exslt.org/regular-expressions"
      xmlns:dpconfig="http://www.datapower.com/param/config"   
      xmlns:dp="http://www.datapower.com/extensions"
      extension-element-prefixes="dp"
    >
      <dp:input-mapping  href="String.utf-8.ffd" type="ffd"/>
      <xsl:output method="text"/>
        
      <xsl:param name="dpconfig:sourceString"/> 
      <xsl:param name="dpconfig:targetString"/>
    
      <xsl:template match="/">
        <xsl:variable name="input" select="/object/message/text()"/>
    
        <xsl:value-of select="regexp:replace($input, 
                                $dpconfig:sourceString, 'g', $dpconfig:targetString
                              )" 
        />
      </xsl:template>
      
    </xsl:stylesheet>
    

     

    replace.2.xsl:

    <xsl:stylesheet version="1.0"
      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
      xmlns:regexp="http://exslt.org/regular-expressions"
      xmlns:dpconfig="http://www.datapower.com/param/config"   
      xmlns:dp="http://www.datapower.com/extensions"
      extension-element-prefixes="dp"
    >
      <dp:input-mapping  href="store:///pkcs7-convert-input.ffd" type="ffd"/>
      <xsl:output method="text"/>
        
      <xsl:param name="dpconfig:sourceString"/> 
      <xsl:param name="dpconfig:targetString"/>
    
      <xsl:template match="/">
        <xsl:variable name="input64"
          select="dp:binary-encode(/object/message/node())"
        />
        <xsl:variable name="input" select="dp:decode($input64, 'base-64')"/>
    
        <xsl:value-of select="regexp:replace($input, 
                                $dpconfig:sourceString, 'g', $dpconfig:targetString
                              )" 
        />
      </xsl:template>
      
    </xsl:stylesheet>
    

     

    Only the first needs String.utf-8.ffd:

    <!--  
        This FFD converts the input into an XML tree like this:
    
        <object>
          <message>***string data***</message> 
        </object> 
    --> 
    <File name="object" syntax="syn">
      <Syntax name="syn" encoding="utf-8"/> 
      <Field name='message' type='String'/>
    </File>
    

     

    Hermann <myBlog/> <myTweets/> | <GraphvizFiddle/> | <xqib/> | <myCE/> <myFrameless/>

  • HermannSW
    HermannSW
    4524 Posts

    Re: Gotta Love GatewayScript and V7

    ‏2014-07-01T10:19:38Z  
    • HermannSW
    • ‏2014-07-01T10:19:08Z

    Hi Joe,

    > We are all upgraded to V7 and started working on a back-log of GatewayScript to handle things. 
    >
    it is good to see your excitement on GatewayScript.


    > Our first, and one of the more painful things to do in XSLT is a simple search and replace.  
    > Here is a highly reusable GatewayScript that will do just that for any string input:
    >
    At least your variable name "xmlData" seems to indicate that you might want to replace strings in XML data by just regexp:replace() and treating XML as just a string. There are a few issues with this:

    • if sourceString is just '>' you will break XML
    • you cannot handle XML because the encoding of stylesheet parameters "sourceString" and "targetString" is UTF-8 and your GatewayScript script only handles UTF-8 encoded (string) input
    • you cannot even make sure input is XML (see attached service export, request type is XML but that does NOT ensure XML input)
    • in general, as long as GatewayScript does not ship XML(crypto) modules XML(crypto) processing should not be done by GatewayScript


    In attached service you will find your script at endpoint "/js", the equivalent XSLT+FFD under "/ffd" and finally XSLT based on shipped FFD under "/shipped" (that does UTF-8 validation of input string in addition).

    Here you see that all do same replacement of German umlaut 'ä' by its (German) equivalent term 'ae', and that GatewayScript cannot handle ISO-8859-1 encoded input string ('ä' is 0xE4 there):

    <pre class="javascript dw" data-editor-lang="js" data-pbcklang="javascript" dir="ltr">$ echo -e "1ä2" | curl --data-binary @- http://dp2-l3:5201/js 1ae2 $ echo -e "1ä2" | curl --data-binary @- http://dp2-l3:5201/ffd 1ae2 $ echo -e "1ä2" | curl --data-binary @- http://dp2-l3:5201/shipped 1ae2 $ $ echo -e "1\xC3\xA42" | curl --data-binary @- http://dp2-l3:5201/js 1ae2 $ echo -e "1\xC3\xA42" | curl --data-binary @- http://dp2-l3:5201/ffd 1ae2 $ echo -e "1\xC3\xA42" | curl --data-binary @- http://dp2-l3:5201/shipped 1ae2 $ $ echo -e "1\xE42" | curl --data-binary @- http://dp2-l3:5201/js 1�2 $ </pre>

     

    > Our first, and one of the more painful things to do in XSLT is a simple search and replace. 
    >
    Again, from my point of view the XSLTs are definitely not more complicated than your script, perhaps even simpler.

    replace.xsl:

    <pre class="javascript dw" data-editor-lang="js" data-pbcklang="javascript" dir="ltr"><xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:regexp="http://exslt.org/regular-expressions" xmlns:dpconfig="http://www.datapower.com/param/config" xmlns:dp="http://www.datapower.com/extensions" extension-element-prefixes="dp" > <dp:input-mapping href="String.utf-8.ffd" type="ffd"/> <xsl:output method="text"/> <xsl:param name="dpconfig:sourceString"/> <xsl:param name="dpconfig:targetString"/> <xsl:template match="/"> <xsl:variable name="input" select="/object/message/text()"/> <xsl:value-of select="regexp:replace($input, $dpconfig:sourceString, 'g', $dpconfig:targetString )" /> </xsl:template> </xsl:stylesheet> </pre>

     

    replace.2.xsl:

    <pre class="javascript dw" data-editor-lang="js" data-pbcklang="javascript" dir="ltr"><xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:regexp="http://exslt.org/regular-expressions" xmlns:dpconfig="http://www.datapower.com/param/config" xmlns:dp="http://www.datapower.com/extensions" extension-element-prefixes="dp" > <dp:input-mapping href="store:///pkcs7-convert-input.ffd" type="ffd"/> <xsl:output method="text"/> <xsl:param name="dpconfig:sourceString"/> <xsl:param name="dpconfig:targetString"/> <xsl:template match="/"> <xsl:variable name="input64" select="dp:binary-encode(/object/message/node())" /> <xsl:variable name="input" select="dp:decode($input64, 'base-64')"/> <xsl:value-of select="regexp:replace($input, $dpconfig:sourceString, 'g', $dpconfig:targetString )" /> </xsl:template> </xsl:stylesheet> </pre>

     

    Only the first needs String.utf-8.ffd:

    <pre class="javascript dw" data-editor-lang="js" data-pbcklang="javascript" dir="ltr"><!-- This FFD converts the input into an XML tree like this: <object> <message>***string data***</message> </object> --> <File name="object" syntax="syn"> <Syntax name="syn" encoding="utf-8"/> <Field name='message' type='String'/> </File> </pre>

     

    Hermann <myBlog/> <myTweets/> | <GraphvizFiddle/> | <xqib/> | <myCE/> <myFrameless/>

     

    Attachments