We saw the power of having a complete programming language for working with XML messages to not only transform the XML but to access API Connect-specific variables and other specialized functions. But what if we are not working with XML? What if we are dealing with a more modernized RESTful service receiving JSON requests and responses? This is where GatewayScript comes in. GatewayScript is nothing more than DataPower’s implementation of JavaScript. Since DataPower is your gateway service, it is only natural that API Connect provides a pre-built policy for implementing your own GatewayScript code. Much like the XSLT policy, GatewayScript also provides the ability to access context and API property variables and is also a complete programming language. If you are not familiar with JavaScript, or just need a refresher, there are many books and resources available on the internet. Much like the previous section on XSLT, we will not cover the basics of this language, just the API Connect-specific details regarding implementation.
To implement your own GatewayScript code, you would begin the same as you did for every other built-in policy by dragging the GatewayScript policy onto the Gateway palette. Once this policy is in place, the configuration screen will become visible, presenting a text editor to enter your GatewayScript code. Again, it would be advisable to maximize this screen to provide an expanded view of this text editor. If your code becomes too long or complex, it may be beneficial for you to work in a text editor or Integrated Development Environment (IDE) and then copy/paste your code into the policy editor when finished.
Let’s again take our JSON version of the createOrder request message and perform the same apply transformation requirements that we had in the XML version. Again, we will want to produce an XML output while adding three additional fields – requestHost, timestamp, and itemCount, as we did in the XSLT example. The big difference here is that we are receiving a JSON message as the request message. This example will demonstrate how we can deal with different message formats, access API Connect-specific variables, and also utilize a built-in JavaScript function. Let’s take a look at our example GatewayScript. Line numbers have been added for ease of reference:
1. var apim = require(‘./apim.custom.js’);
// var apim = require(‘apim’);
2. apim.readInputAsJSON(function (error, json) {
3. if (error)
4. {
5. apim.error(‘Parse Error’, 500, ‘Internal Error’,
‘Failed to parse JSON input’);
6. }
7. else
8. {
9. var d = new Date();
10. var itemCount = json.createOrder.items.length;
11. var xml = “<createOrder>”;
12. xml += “<customerId>” + json.createOrder.customerId
+ “</customerId>”;
13. xml += “<timestamp>” + d.toISOString() +
“</timestamp>”;
14. xml += “<requestHost>” +
apim.getvariable(‘request.headers.host’) +
“</requestHost>”;
15. xml += “<itemCount>” + itemCount + “</itemCount>”;
16. for (var i = 0; i < json.createOrder.items.length;
i++){
17. xml += “<items>”;
18. xml += “<itemNumber>” + json.createOrder.items
[i].itemNumber + “</itemNumber>”;
19. xml += “<itemQuantity>” + json.createOrder.items
[i].itemQuantity + “</itemQuantity>”;
20. xml += “<itemDescription>” +
json.createOrder.items[i].itemDescription +
“</itemDescription>”;
21. xml += “</items>”;
22. }
23. xml += “</createOrder>”;
24. session.output.write(XML.parse(xml));
25. apim.output(‘application/xml’);
26. }});
Just as we had to provide an import statement with our XSLT so that we can reference built-in API Connect functions, we will need to do the same for our GatewayScript. Line 1 in our code shows how we set an apim variable and added the require statement. The parameter passed to the require() function will be different if you have your gateway services set to be V5 compatible or not. For V5-compatible gateways, you will set this as ./apim.custom.js, whereas API gateways will require apim.
Since we know that we should be expecting a JSON request message as input to the GatewayScript, we must specify in our GatewayScript to read in the data as JSON, which is what we are doing in line 2 in our sample code. We then proceed to some error handling in case there is an issue parsing the incoming JSON.
Once all of our housekeeping is done upfront, we can now begin to get the values for our new XML request. You can see a JavaScript function being used in line 9 to obtain the current date and time, which will be converted to a string in line 13 where we use it. Line 10 is a good example where we obtain the total number of items in the JSON array to be used for our itemCount element. It is also interesting to see here how you can navigate through the incoming JSON message using a dot notation. This will be more apparent as you look through how we populate the output XML elements.
We build our output XML message by simply appending to one variable named xml throughout the code, being certain to include the proper XML begin and end tags. Again, we can populate these XML elements with the incoming JSON data by referencing the JSON elements via the dotted notation. On line 16, you can see that we begin a for loop, iterating through the incoming JSON array and populating our XML document.
Finally, we have completed our XML document and are ready to send it to the output stream. To do this, we use the session.output.write() function, as you can see in line 24. As you can see, we do not just pass in our string that we have been using to build our XML document. We have to be sure to parse this as XML, using the XML.parse() function. Once we have set the output, we must then use the API Connect function, apim.output(), to set the output to application/xml.
Once we have coded our GatewayScript in our policy, we can save the API and publish it so that it can be invoked. Figure 8.21 shows a sample request and response to our API that converted our JSON request into an XML document while adding a few new fields:
Figure 8.21 – JSON to XML transformation using GatewayScript
You have now been introduced to the GatewayScript policy and only scratched the surface with the capabilities of the language itself. We have demonstrated a few of the capabilities to get you started; however, you are encouraged to experiment and discover all of the capabilities that it has to offer.
Summary
As our technology landscape continues to evolve, so will the latest and greatest formats for communicating and sharing data. It feels like just yesterday that service-oriented architecture was going to change our world using SOAP messages and WSDLs. Then, just as we all got our service converted to facilitate the use of SOAP messages, it became RESTful services and JSON was all the rage. It would be extremely difficult to keep up with these technology and architecture shifts with all of our applications and systems; however, we will need to expose our legacy service to our modernized consumers using the latest and greatest. This is where the power of message transformation comes into play.
You have seen how we can easily transform our message from one format to another, or enrich the data as it comes in. You have also seen how API Connect provides built-in policies for some very specific use cases and transformations, making it a simple drag and drop configuration. Of course, there will be more complex scenarios, as we demonstrated with the two programming languages, that will give you total control and flexibility. Choosing the proper built-in policy for your transformations will allow you to quickly configure these policies and provide the most performant and efficient solution when it comes to runtime.
Throughout this chapter, you have learned about the built-in, drag and drop features within APIC to perform your message transformations. For cases where these do not quite fit the bill, you have also learned how to customize your own message transformations using two powerful programming languages. Armed with this knowledge, you are now equipped to implement almost any type of message transformation you might have.
If the custom programming within this chapter piqued your interest, be sure to continue on to the next chapter, where you will be introduced to the GraphQL features within APIC, providing even more flexibility and customization for your APIs.