DataPower API Gateway
only

Using context variables in GatewayScript and XSLT policies with the DataPower API Gateway

In the code for GatewayScript and XSLT policies in your API assemblies, you can use API context variables to work with the messages that are generated when an API is called.

Introduction

All API context variables are stored in a JSON-like tree; each context variable is a node in this tree. A non-leaf node can be either an object or an array, while a leaf node can be a number, string, boolean, or document; a document can contain an XML document, BLOB, Stream, or another JSON document.

Each context variable has a name and a value. You can access a context variable by name when using the GatewayScript and XSLT APIs. Dot notation is used to access a context variable, reflecting the position of the corresponding node in the JSON-like tree; for example, request.headers.Host. Where a node name contains special characters, bracket notation is supported; for example, request.headers['Content-Type'].

For the GatewayScript policy, all the APIs for the DataPower® API Gateway are in the context module, which is a global module. You can therefore access the context module directly, you do not need to use the require() function first.

For the XSLT policy, the APIs are in the http://www.ibm.com/xmlns/datapower/2017/11/apigateway namespace; to use these APIs you must declare this namespace.

Note: The mechanisms described here for interacting with the API Connect context are preferred if you are writing new GatewayScript policy, XSLT policy, or user-defined policy code, and provide the best performance. For mechanisms that are compatible with Version 5, see GatewayScript code examples.

Accessing context variables - examples

GatewayScript examples
To read the client.app.id context variable:
var clientID = context.get('client.app.id');
To set the value of a context variable:
context.set('my.vars.amount', 100);
The resulting tree has the following structure:
{ "my": { "vars": { "amount": 100 } } }
To delete the node my.vars, and all its child nodes:
context.clear('my.vars');
The resulting tree has the following structure:
{ "my": { } }
XSLT examples
To read the client.app.id context variable:
<xsl:variable name="clientID" select="apigw:get-variable('client.app.id')"/>
To set the value of a context variable:
<apigw:set-variable name="'my.vars.amount'" value="100"/>
The resulting tree has the following structure:
{ "my": { "vars": { "amount": 100 } } }
To delete the node my.vars, and all its child nodes:
<apigw:clear-variable name="'my.vars'"/>
The resulting tree has the following structure:
{ "my": { } }

About payloads

When the assembly flow for an API call begins, the following two message objects are predefined in the API context tree:
  • request: holds the information for the original payload; the request message is a read-only object.
  • message: holds the information for the current payload.
Typically, a message object has headers and body properties. For the current payload, the message object might have variables and status properties, as well as other properties created during the execution of the assembly.
The following example shows the general structure of a typical message:
{
  "headers": {
    "Content-Type": "application/xml",
    "X-Client-ID": "1234567890"
  },
  "variables": {
    "amount": 123,
    "name": "xyz"
  },
  "status": {
    "code": 200,
    "reason": "OK"
  },
  "body": <XML/Blob/Stream/JSON Document>
}

Manipulating the message headers - examples

Note: Do not attempt to use this method to add fields to Analytics data. Using an Analytics filter is the only supported way to add top-level Analytics fields.
GatewayScript examples
To delete a header:
context.message.header.remove('X-My-Header');
To read a header:
var reqType = context.request.header.get('Content-Type');
var currType = context.message.header.get('Content-Type');
To set a header:
context.message.header.set('Content-Type', 'application/json');
To iterate through the headers:
var reqHdrs = context.request.headers;
for (var h in reqHdrs) {
   console.log('>>> Reading the request header: ', h, '=', reqHdr[h]);
} 

var currHdrs = context.message.headers;
for (var h in currHdrs) {
   console.log('>>> Reading the current header: ', h, '=', currHdr[h]);
} 
To create a message context called headersContext, if one doesn't already exist, and add to it a boolean context variable called HelloWorld, with the value true:
var ctx = context.getMessage("headersContext") || context.createMessage("headersContext");
ctx.setVariable('HelloWorld', true);
The setVariable call writes the variable into headersContext.variables.HelloWorld; therefore a condition statement in any subsequent switch policy should check for headersContext.variables.HelloWorld rather than headersContext.HelloWorld.
To read the context variable in any subsequent gatewayscript policy, use the following call:
ctx.getVariable("HelloWorld")
Note: If you are either migrating an API from IBM® API Connect Version 5.0, or from the DataPower Gateway (v5 compatible), to the DataPower API Gateway, or you are configuring a new API for the DataPower API Gateway, creating a message context, rather than using the context variable mechanism described in Accessing context variables - examples, is the preferred option. In the case of migration, it most closely matches the behavior of IBM API Connect Version 5.0, and setVariable and getVariable calls will continue to work without modification.

Creating a message context is also the preferred option if you are creating a new API for the DataPower API Gateway because it most closely aligns the API context with the way that various native DataPower API Gateway policies process it.

XSLT examples
To delete a header:
<apigw:clear-header message="'message'" name="'X-My-Header'"/>
To read a header:
<xsl:variable name="reqType" select="apigw:get-header('request', 'Content-Type')"/>
<xsl:variable name="currType" select="apigw:get-header('message', 'Content-Type')"/>
To set a header:
<apigw:set-header name="'Content-Type'" value="'text/xml'"/>
To get all headers:
<xsl:variable name="allReqHdrs" select="apigw:all-headers("'request'")"/>
<xsl:variable name="allCurrHdrs" select="apigw:all-headers("'message'")"/>

Manipulating the message status - examples

Note: Only the message object has the status property, not the request object.
GatewayScript examples
To read the status code and reason phrase:
var code = context.message.statusCode;
var reason = context.message.reasonPhrase;
To update the status code:
context.message.statusCode = 400; //integer, update the code, with default reason
To update the status code and reason phrase in a single operation:
context.message.statusCode = '200 Wonderful'; //string, update code along with customized reason
Note: The context.message.reasonPhrase context variable is read-only.
XSLT examples
To read the status code and reason phrase:
<xsl:variable name="code" select="apigw:get-variable('message.status.code')"/>
<xsl:variable name="reason" select="apigw:get-variable('message.status.reason')"/>
<apigw:set-variable name="'message.status.code'" value="200"/>
<apigw:set-variable name="'message.status.reason'" value="'OK'"/>

Accessing the message body - examples

Note: The request body is read-only.
GatewayScript examples
To read the request body:
context.request.body.readAsJSON(function(error, json) {});
context.request.body.readAsXML(function(error, xml) {});
context.request.body.readAsBuffer(function(error, buffer) {});
To read the message body:
context.message.body.readAsJSON(function(error, json) {});
context.message.body.readAsXML(function(error, xml) {});
context.message.body.readAsBuffer(function(error, buffer) {});
To write the message body and update the content type accordingly:
// text response
context.message.body.write("Hello world.");
context.message.header.set('Content-Type', "text/plain");

// JSON response
var pet = { "kind": "dog", "age": 3, "color": "black" };
context.message.body.write(pet);
context.message.header.set('Content-Type', "application/json");

// XML response
var resp = "<order><id>100</id><timestamp>20181231</timestamp><status>fulfilled</status></order>";
context.message.body.write(resp);
context.message.header.set('Content-Type', "text/xml");
XSLT examples
Note:
  • There is no XSLT API to write the message body; the output of the stylesheet transformation is used to update message.body.
  • To read the request body or the message body, you must parse message.body with a Parse policy before the XSLT policy is executed. At the beginning of the assembly flow, message.body contains request.body so, after parsing message.body, you can then read the request from message.body.
  • If the XSLT input document uses the context current payload, message.body is used for the input document '/' that can be accessed from the XSLT policy if message.body has been parsed as XML in advance; this is determined by the input property of the XSLT policy, see xslt.
Read the message body:
<xsl:variable name="currentPayload" select="apigw:read-payload('message')" />
Read the message body when the input property of the XSLT policy is set to true:
<xsl:variable name="currentPayload" select="/" />

Rejecting the session - examples

Note: After the session is rejected, the API assembly flow is stopped and a fault response is returned, unless a catch handler is defined.
GatewayScript examples
To reject the session with an error name and message, and update the status reason and code:
context.reject('CustomError', 'You are not authorized to make this API call');
context.message.statusCode = '401 Unauthorized';
XSLT examples
To reject the session with an error name and message, and update the status reason and code:
<apigw:reject identifier="'CustomError'" status-code="401" reason="'Unauthorized'">You are not authorized to make this API call</apigw:reject>