Topic
  • 5 replies
  • Latest Post - ‏2017-08-03T11:29:31Z by HermannSW
softwareguidance.chintala.gmail
79 Posts

Pinned topic Converting an XSL to Gateway Script? Help Needed

‏2017-08-01T14:52:51Z | datapower gatewayscript hermannsw

Hello guys,

I'm new to datapower and XSL world.

I had issues handling binary Data ( JSON) while using dp:ur-open function in XSL.

HermannSW ,one our user/admin community, has suggested to use Gateway scripts to handle JSON.

I would urge help from our dev community to help me understand how to implement all we did in XSL in Gateway Scripts.

My XSL:

  1. <xsl:output omit-xml-declaration="yes" encoding="UTF-8" method="text"/>
  2. <xsl:variable name="dpuriIn" select="dp:variable('var://service/URL-in')"/>
  3. <xsl:variable name="dpuri" select="dp:variable('var://service/URI')"/>
  4. <xsl:variable name="year" select="substring-after($dpuri,'vehicles/')"/>
  5. <xsl:variable name="ContentType" select="dp:http-request-header('Content-Type')"/>
  6. <xsl:variable name="AppContentType" select="dp:http-request-header('App-Content-Type')"/>
  7. <xsl:template match="/">
  8. <xsl:message dp:priority="debug">
  9. dpuri: <xsl:copy-of select="$dpuri"/>
  10. </xsl:message>
  11. <xsl:message dp:priority="debug">
  12. year: <xsl:copy-of select="$year"/>
  13. </xsl:message>
  14.  
  15. <xsl:variable name="BackendURL" select="document('local:/Catalog/XML/Catalog-Routes.xml')/CalloutURLS"/>
  16. <xsl:variable name="ShareInt">
  17. <xsl:value-of select="$BackendURL/CalloutURL[ServiceName='SHAREINT']//following-sibling::URL"/>
  18. </xsl:variable>
  19. <xsl:variable name="ShareIntEndpoint">
  20. <xsl:value-of select="concat($ShareInt,$year )"/>
  21. <!-- Setting Cache GET URL with our VIN-->
  22. </xsl:variable>
  23. <xsl:variable name="json2xmlEndpoint">
  24. <xsl:value-of select="$BackendURL/CalloutURL[ServiceName='JSON2XML']//following-sibling::URL"/>
  25. </xsl:variable>
  26. <xsl:variable name="cacheURL1">
  27. <xsl:value-of select="$BackendURL/CalloutURL[ServiceName='GETCACHE']//following-sibling::URL"/>
  28. </xsl:variable>
  29. <xsl:variable name="PostCache">
  30. <xsl:value-of select="$BackendURL/CalloutURL[ServiceName='POSTCACHE']//following-sibling::URL"/>
  31. </xsl:variable>
  32.  
  33.  
  34. <xsl:choose>
  35. <xsl:when test="($ContentType or $AppContentType) != 'application/json'">
  36.  
  37.  
  38. { "error": { "code": "400", "message": "Please check Content-Type" }}
  39.  
  40. <xsl:variable name="code" select="'400'"/>
  41. <xsl:variable name="text" select="' Bad Request'"/>
  42. <dp:set-http-response-header name="'x-dp-response-code'" value="'-1 exampleReasonPhrase'"/>
  43. <dp:append-response-header name="'x-dp-response-code'" value="concat($code,$text)"/>
  44. <dp:set-http-request-header name="'Content-Type'" value="'application/json'"/>
  45. </xsl:when>
  46. <!-- Checking is dealerCode -->
  47. <xsl:when test=" $year = '' ">
  48. { "error": { "code": "400", "message": "Please enter a Year" }}
  49. <xsl:variable name="code" select="'400'"/>
  50. <xsl:variable name="text" select="' Bad Request'"/>
  51. <dp:set-http-response-header name="'x-dp-response-code'" value="'-1 exampleReasonPhrase'"/>
  52. <dp:append-response-header name="'x-dp-response-code'" value="concat($code,$text)"/>
  53. <dp:set-http-request-header name="'Content-Type'" value="'application/json'"/>
  54. </xsl:when>
  55. <xsl:otherwise>
  56. <xsl:variable name="Key">
  57. <xsl:value-of select="concat('Catalog-',$year )"/>
  58. <!-- Setting Cache GET URL with our VIN-->
  59. </xsl:variable>
  60.  
  61. <xsl:variable name="httpCacheHeaders">
  62. <!-- Setting Cache Headers-->
  63. <header name="Authorization">Basic ZWFpLXN1cHBvcnQtdXNyOkVBSSNTdXBwMHJ0QDIwMTc=</header>
  64. <header name="Content-Type">application/json</header>
  65. <header name="Accept">application/json</header>
  66. </xsl:variable>
  67. <xsl:variable name="cacheURL2">
  68. <xsl:value-of select="concat($cacheURL1,$Key )"/>
  69. <!-- Setting Cache GET URL with our VIN-->
  70. </xsl:variable>
  71. <xsl:variable name="cacheURL">
  72. <xsl:value-of select="concat($cacheURL2,'&amp;map=RetailCatalog' )"/>
  73. </xsl:variable>
  74. <xsl:variable name="cacheResponse">
  75. <dp:url-open target="{$cacheURL}" response="binaryNode" http-method="get" http-headers="$httpCacheHeaders"/>
  76. <!-- Calling getCache-->
  77. </xsl:variable>
  78.  
  79. <xsl:variable name="getcachejson">
  80. <xsl:value-of select="dp:decode( dp:binary-encode($cacheResponse/result/binary/node()), 'base-64' )"/>
  81. </xsl:variable>
  82. <dp:set-http-response-header name="'Content-Type'" value="'application/json'"/>
  83. <xsl:variable name="responseXml">
  84. <dp:url-open target="{$json2xmlEndpoint}" response="responsecode" http-method="post" http-headers="$httpHeaders" timeout="60">
  85. <xsl:value-of select="normalize-space($getcachejson)"/>
  86. </dp:url-open>
  87. </xsl:variable>
  88. <xsl:variable name="Value">
  89. <xsl:value-of select="$responseXml//response/Root/eaiResponse/response/value"/>
  90. </xsl:variable>
  91. <xsl:variable name="CacheOutput" select="dp:decode($Value,'base-64')"/>
  92. <!-- <dp:set-variable name="'var://service/routing-url'" value="$CacheOutput"/>-->
  93. <xsl:choose>
  94. <xsl:when test="$Value=''">
  95. <!--Cache is EMPTY -->
  96. <xsl:variable name="httpHeaders">
  97. <header name="Content-Type">application/json</header>
  98. <header name="Accept">application/json</header>
  99. </xsl:variable>
  100. <!-- Sending Request to Backend-->
  101.  
  102. <!-- <dp:set-variable name="'var://service/routing-url'" value="$ShareIntEndpoint"/>-->
  103. <xsl:variable name="Response">
  104. <dp:url-open target="{$ShareIntEndpoint}" response="binaryNode" http-headers="$httpHeaders" http-method="get"/>
  105. </xsl:variable>
  106. <xsl:message dp:priority="debug"><!-- <xsl:copy-of select="/object/message/node()"/> -->
  107. ShareIntEndpoint Response: <xsl:copy-of select="$Response/result/binary/node()"/>
  108. </xsl:message>
  109. <xsl:variable name="ShareIntJSON">
  110. <xsl:value-of select="dp:decode( dp:binary-encode($Response/result/binary/node()), 'base-64' )"/>
  111. </xsl:variable>
  112. <xsl:message dp:priority="debug">
  113. ShareIntEndpoint ShareIntJSON: <xsl:copy-of select="$ShareIntJSON"/>
  114. </xsl:message>
  115. <xsl:variable name="responsecode" select="$Response/result/responsecode/node()"/>
  116. <xsl:message dp:priority="debug">
  117. ShareIntEndpoint responsecode: <xsl:copy-of select="$responsecode"/>
  118. </xsl:message>
  119. <xsl:choose>
  120.  
  121. <xsl:when test="$responsecode='200'">
  122.  
  123.  
  124. <xsl:variable name="encodedResponse" select="dp:encode($ShareIntJSON,'base-64')"/>
  125. <dp:url-open target="{$PostCache}" response="responsecode-binary" http-headers="$httpCacheHeaders" http-method="post">
  126.  
  127. {
  128. "Cache": {
  129. "Grid": "Grid",
  130. "Value": "<xsl:copy-of select="$encodedResponse"/>",
  131. "Key":"Catalog-<xsl:value-of select="$year"/>",
  132. "Map": "RC",
  133. "TTL": "90000"
  134. }
  135. }
  136. </dp:url-open>
  137.  
  138. <xsl:copy-of select="$ShareIntJSON"/>
  139. <dp:set-http-response-header name="'x-dp-response-code'" value="'200 OK'"/>
  140. <dp:set-http-request-header name="'Content-Type'" value="'application/json'"/>
  141. </xsl:when>
  142. <xsl:when test="$responsecode='204'">
  143. <xsl:copy-of select="$ShareIntJSON"/>
  144. <xsl:variable name="code" select="'204'"/>
  145. <xsl:variable name="text" select="' No Content'"/>
  146. <dp:set-http-response-header name="'x-dp-response-code'" value="'-1 exampleReasonPhrase'"/>
  147. <dp:append-response-header name="'x-dp-response-code'" value="concat($code,$text)"/>
  148. <dp:set-http-request-header name="'Content-Type'" value="'application/json'"/>
  149. </xsl:when>
  150. <xsl:when test="$responsecode='400'">
  151. <xsl:copy-of select="$ShareIntJSON"/>
  152. <xsl:variable name="code" select="'400'"/>
  153. <xsl:variable name="text" select="' Bad Request'"/>
  154. <dp:set-http-response-header name="'x-dp-response-code'" value="'-1 exampleReasonPhrase'"/>
  155. <dp:append-response-header name="'x-dp-response-code'" value="concat($code,$text)"/>
  156. <dp:set-http-request-header name="'Content-Type'" value="'application/json'"/>
  157. </xsl:when>
  158.  
  159. <xsl:otherwise>
  160.  
  161.  
  162. <xsl:copy-of select="$ShareIntJSON"/>
  163. <dp:set-http-response-header name="'x-dp-response-code'" value="'500 INTERNAL SERVER ERROR'"/>
  164. <dp:set-http-request-header name="'Content-Type'" value="'application/json'"/>
  165.  
  166. </xsl:otherwise>
  167. </xsl:choose>
  168. </xsl:when>
  169. <xsl:otherwise>
  170. <!-- Cache has DATA -->
  171.  
  172. <xsl:copy-of select="$CacheOutput"/>
  173. <dp:set-http-response-header name="'x-dp-response-code'" value="'200 OK'"/>
  174. <dp:set-http-request-header name="'Content-Type'" value="'application/json'"/>
  175.  
  176. </xsl:otherwise>
  177.  
  178. </xsl:choose>
  179.  
  180. </xsl:otherwise>
  181. </xsl:choose>
  182. </xsl:template>
  183.  
  184.  

I would like to get the same functionalities usinga Gateway script.

The basic flow is like following: 1.) Check header values , if not appropriate, throw Error with HTTP Status Code 400 2.) Read document from Local for URLs 3.)Call 1st endpoint, which returns JSON response. Has an attribute "value". 4.)Check value is empty or null 5.) If null, call URL2, which returns JSON body. 6.) Check HTTP status code for URL2. 7.) If status code is 200, display response from URL2, with 200 OK and call URL 3 to a POST method. 8.) if 400/404/204, display reponse from URL 2 with corresponding HTTP status code and meesage from URl2.

This is the flow.

Please advise on how to do so. I undertsand we would need header modules, url open modules, But I'm not pretty sure of the syntax.

This would be a good starting point for me to start scripts instead of XSL.

  • benNeil
    benNeil
    69 Posts
    ACCEPTED ANSWER

    Re: Converting an XSL to Gateway Script? Help Needed

    ‏2017-08-01T18:52:14Z  
    1.  
    2.  
    3.  
    4.  
    5. Hi Sai,
    6.  
    7. I tried following piece of code. since it's a way big I need sometime.

    8. <xsl:output omit-xml-declaration="yes" encoding="UTF-8" method="text"/>
    9. <xsl:variable name="dpuriIn" select="dp:variable('var://service/URL-in')"/>
    10. <xsl:variable name="dpuri" select="dp:variable('var://service/URI')"/>
    11. <xsl:variable name="year" select="substring-after($dpuri,'vehicles/')"/>
    12. <xsl:variable name="ContentType" select="dp:http-request-header('Content-Type')"/>
    13. <xsl:variable name="AppContentType" select="dp:http-request-header('App-Content-Type')"/>
    14. <xsl:template match="/">
    15. <xsl:message dp:priority="debug">
    16. dpuri: <xsl:copy-of select="$dpuri"/>
    17. </xsl:message>
    18. <xsl:message dp:priority="debug">
    19. year: <xsl:copy-of select="$year"/>
    20. </xsl:message>
    21.  
    22. <xsl:variable name="BackendURL" select="document('local:/Catalog/XML/Catalog-Routes.xml')/CalloutURLS"/>

     

    var urlopen = require ('urlopen');
    var service = require('service-metadata');
    var transform = require('transform');
    var hm = require('header-metadata');


    var dpuriIn = service.getVar('var://service/URL-in');
    var dpuri   = service.getVar('var://service/URI');
      var subAfter = 'vehicles/';
      var year = str.substring(str.indexOf(subAfter) + subAfter.length);
    var all_Headers = hm.current.headers;
    var contentType = hm.current.get('content-type');
    var App-Content-Type = hm.current.get('App-Content-Type');
    console.debug(dpuri);
    console.debug(year);
     

     var options = {
        target: 'local:///Catalog/XML/Catalog-Routes.xml',
        // method is optional. By default, method is get.
        method: 'get',
    };


    urlopen.open (options, function (error, response) {
        if (error) {
            // an error occurred during reading the file
            session.output.write ("urlopen error: " + JSON.stringify(error));
        } else {
            // read response data
            // response.statusCode === 200: Successfully open file
            // response.statusCode === 403: Permission denied (e.g. store:///dp is write only, cannot read)
            // response.statusCode === 404: File not found
            // response.statusCode === 500: Other open file error
            var responseStatusCode = response.statusCode;
            if (responseStatusCode == 200) {
                response.readAsBuffer(function(error, responseData) {
                    if (error) {
                        // error while reading response or transferring data to Buffer
                        session.output.write("readAsBuffer error: " + JSON.stringify(error));
                    } else {
                        session.output.write(responseData);
                    } 
                });
            } else {
                session.output.write ("urlopen target return statusCode " + responseStatusCode);
            }
        }
    }); // end of urlopen.open()

     

    Thanks,

    Ben

  • HermannSW
    HermannSW
    8602 Posts

    Re: Converting an XSL to Gateway Script? Help Needed

    ‏2017-08-01T16:10:39Z  

    > I undertsand we would need header modules, url open modules, But I'm not pretty sure of the syntax.
    >

    Knowledge Center describes the APIs in detail, with samples:

    https://www.ibm.com/support/knowledgecenter/SS9H2Y_7.5.0/com.ibm.dp.doc/gatewayscript_model.html

    You need these modules:

    https://www.ibm.com/support/knowledgecenter/SS9H2Y_7.5.0/com.ibm.dp.doc/service-metadata_js.html

    https://www.ibm.com/support/knowledgecenter/SS9H2Y_7.5.0/com.ibm.dp.doc/urlopen_js.html

    https://www.ibm.com/support/knowledgecenter/SS9H2Y_7.5.0/com.ibm.dp.doc/fs_js.html

    https://www.ibm.com/support/knowledgecenter/SS9H2Y_7.5.0/com.ibm.dp.doc/console_js.html

    probably more

     

    For base64 encoding/decoding:

    https://www.ibm.com/developerworks/community/forums/html/topic?id=b032ad8b-5ec8-4363-ae3c-82f7e2d60904

     

    Hermann.

  • softwareguidance.chintala.gmail
    79 Posts

    Re: Converting an XSL to Gateway Script? Help Needed

    ‏2017-08-01T17:09:43Z  
    • HermannSW
    • ‏2017-08-01T16:10:39Z

    Thanks Hermann,

     

    Can you please share any sample Scripts where I can use for reference and learn from there.

     

    Hope you understand.

     

    Thanks.

  • benNeil
    benNeil
    69 Posts

    Re: Converting an XSL to Gateway Script? Help Needed

    ‏2017-08-01T18:52:14Z  
    1.  
    2.  
    3.  
    4.  
    5. Hi Sai,
    6.  
    7. I tried following piece of code. since it's a way big I need sometime.

    8. <xsl:output omit-xml-declaration="yes" encoding="UTF-8" method="text"/>
    9. <xsl:variable name="dpuriIn" select="dp:variable('var://service/URL-in')"/>
    10. <xsl:variable name="dpuri" select="dp:variable('var://service/URI')"/>
    11. <xsl:variable name="year" select="substring-after($dpuri,'vehicles/')"/>
    12. <xsl:variable name="ContentType" select="dp:http-request-header('Content-Type')"/>
    13. <xsl:variable name="AppContentType" select="dp:http-request-header('App-Content-Type')"/>
    14. <xsl:template match="/">
    15. <xsl:message dp:priority="debug">
    16. dpuri: <xsl:copy-of select="$dpuri"/>
    17. </xsl:message>
    18. <xsl:message dp:priority="debug">
    19. year: <xsl:copy-of select="$year"/>
    20. </xsl:message>
    21.  
    22. <xsl:variable name="BackendURL" select="document('local:/Catalog/XML/Catalog-Routes.xml')/CalloutURLS"/>

     

    var urlopen = require ('urlopen');
    var service = require('service-metadata');
    var transform = require('transform');
    var hm = require('header-metadata');


    var dpuriIn = service.getVar('var://service/URL-in');
    var dpuri   = service.getVar('var://service/URI');
      var subAfter = 'vehicles/';
      var year = str.substring(str.indexOf(subAfter) + subAfter.length);
    var all_Headers = hm.current.headers;
    var contentType = hm.current.get('content-type');
    var App-Content-Type = hm.current.get('App-Content-Type');
    console.debug(dpuri);
    console.debug(year);
     

     var options = {
        target: 'local:///Catalog/XML/Catalog-Routes.xml',
        // method is optional. By default, method is get.
        method: 'get',
    };


    urlopen.open (options, function (error, response) {
        if (error) {
            // an error occurred during reading the file
            session.output.write ("urlopen error: " + JSON.stringify(error));
        } else {
            // read response data
            // response.statusCode === 200: Successfully open file
            // response.statusCode === 403: Permission denied (e.g. store:///dp is write only, cannot read)
            // response.statusCode === 404: File not found
            // response.statusCode === 500: Other open file error
            var responseStatusCode = response.statusCode;
            if (responseStatusCode == 200) {
                response.readAsBuffer(function(error, responseData) {
                    if (error) {
                        // error while reading response or transferring data to Buffer
                        session.output.write("readAsBuffer error: " + JSON.stringify(error));
                    } else {
                        session.output.write(responseData);
                    } 
                });
            } else {
                session.output.write ("urlopen target return statusCode " + responseStatusCode);
            }
        }
    }); // end of urlopen.open()

     

    Thanks,

    Ben

  • softwareguidance.chintala.gmail
    79 Posts

    Re: Converting an XSL to Gateway Script? Help Needed

    ‏2017-08-01T21:41:01Z  
    • benNeil
    • ‏2017-08-01T18:52:14Z
    1.  
    2.  
    3.  
    4.  
    5. Hi Sai,
    6.  
    7. I tried following piece of code. since it's a way big I need sometime.

    8. <xsl:output omit-xml-declaration="yes" encoding="UTF-8" method="text"/>
    9. <xsl:variable name="dpuriIn" select="dp:variable('var://service/URL-in')"/>
    10. <xsl:variable name="dpuri" select="dp:variable('var://service/URI')"/>
    11. <xsl:variable name="year" select="substring-after($dpuri,'vehicles/')"/>
    12. <xsl:variable name="ContentType" select="dp:http-request-header('Content-Type')"/>
    13. <xsl:variable name="AppContentType" select="dp:http-request-header('App-Content-Type')"/>
    14. <xsl:template match="/">
    15. <xsl:message dp:priority="debug">
    16. dpuri: <xsl:copy-of select="$dpuri"/>
    17. </xsl:message>
    18. <xsl:message dp:priority="debug">
    19. year: <xsl:copy-of select="$year"/>
    20. </xsl:message>
    21.  
    22. <xsl:variable name="BackendURL" select="document('local:/Catalog/XML/Catalog-Routes.xml')/CalloutURLS"/>

     

    var urlopen = require ('urlopen');
    var service = require('service-metadata');
    var transform = require('transform');
    var hm = require('header-metadata');


    var dpuriIn = service.getVar('var://service/URL-in');
    var dpuri   = service.getVar('var://service/URI');
      var subAfter = 'vehicles/';
      var year = str.substring(str.indexOf(subAfter) + subAfter.length);
    var all_Headers = hm.current.headers;
    var contentType = hm.current.get('content-type');
    var App-Content-Type = hm.current.get('App-Content-Type');
    console.debug(dpuri);
    console.debug(year);
     

     var options = {
        target: 'local:///Catalog/XML/Catalog-Routes.xml',
        // method is optional. By default, method is get.
        method: 'get',
    };


    urlopen.open (options, function (error, response) {
        if (error) {
            // an error occurred during reading the file
            session.output.write ("urlopen error: " + JSON.stringify(error));
        } else {
            // read response data
            // response.statusCode === 200: Successfully open file
            // response.statusCode === 403: Permission denied (e.g. store:///dp is write only, cannot read)
            // response.statusCode === 404: File not found
            // response.statusCode === 500: Other open file error
            var responseStatusCode = response.statusCode;
            if (responseStatusCode == 200) {
                response.readAsBuffer(function(error, responseData) {
                    if (error) {
                        // error while reading response or transferring data to Buffer
                        session.output.write("readAsBuffer error: " + JSON.stringify(error));
                    } else {
                        session.output.write(responseData);
                    } 
                });
            } else {
                session.output.write ("urlopen target return statusCode " + responseStatusCode);
            }
        }
    }); // end of urlopen.open()

     

    Thanks,

    Ben

    Thanks a ton Ben!

    That would be a great start for me :)

     

    Can you please tell me how to decode a base64 string using gw script.

    value has a JSON body encoded in base64.

    I'm doing this:

    var value="eyJtZXNzYWdlIjoiSGVsbG8ifQ==";

    var dec2=(new Buffer(value), 'base64').toString('ascii');
    // Outputs decoded data
    console.log("DEC2:"+dec2);
    headers.response.statusCode="200 OK";
    session.output.write(buffer.toString());

     

     

  • HermannSW
    HermannSW
    8602 Posts

    Re: Converting an XSL to Gateway Script? Help Needed

    ‏2017-08-03T11:29:31Z  

    Thanks a ton Ben!

    That would be a great start for me :)

     

    Can you please tell me how to decode a base64 string using gw script.

    value has a JSON body encoded in base64.

    I'm doing this:

    var value="eyJtZXNzYWdlIjoiSGVsbG8ifQ==";

    var dec2=(new Buffer(value), 'base64').toString('ascii');
    // Outputs decoded data
    console.log("DEC2:"+dec2);
    headers.response.statusCode="200 OK";
    session.output.write(buffer.toString());

     

     

    ➫ https://www.ibm.com/developerworks/community/forums/html/topic?id=b032ad8b-5ec8-4363-ae3c-82f7e2d60904