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.
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.
Accessing context variables
- 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:
The resulting tree has the following structure:context.set('my.vars.amount', 100);
{ "my": { "vars": { "amount": 100 } } }
To delete the nodemy.vars
, and all its child nodes:
The resulting tree has the following structure:context.clear('my.vars');
{ "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:
The resulting tree has the following structure:<apigw:set-variable name="'my.vars.amount'" value="100"/>
{ "my": { "vars": { "amount": 100 } } }
To delete the nodemy.vars
, and all its child nodes:
The resulting tree has the following structure:<apigw:clear-variable name="'my.vars'"/>
{ "my": { } }
About payloads
request
: holds the information for the original payload; therequest
message is a read-only object.message
: holds the information for the current payload.
headers
and body
properties.
For the current payload, the message
message object might have
variables
and status
properties, and other properties created
during the execution of the assembly.{
"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
- 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, '=', reqHdrs[h]); } var currHdrs = context.message.headers; for (var h in currHdrs) { console.log('>>> Reading the current header: ', h, '=', currHdrs[h]); }
To create a message context calledheadersContext
, if one doesn't already exist, and add to it a boolean context variable calledHelloWorld
, with the valuetrue
:
Thevar ctx = context.getMessage("headersContext") || context.createMessage("headersContext"); ctx.setVariable('HelloWorld', true);
setVariable
call writes the variable intoheadersContext.variables.HelloWorld
; therefore a condition statement in any subsequentswitch
policy should check forheadersContext.variables.HelloWorld
rather thanheadersContext.HelloWorld
.To read the context variable in any subsequentgatewayscript
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, is the preferred option. In the case of migration, it most closely matches the behavior of IBM API Connect Version 5.0, andsetVariable
andgetVariable
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
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: Thecontext.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
- 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
containsrequest.body
so, after parsingmessage.body
, you can then read the request frommessage.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 ifmessage.body
has been parsed as XML in advance; this is determined by theinput
property of the XSLT policy, see xslt.
- There is no XSLT API to write the message body; the output of the stylesheet transformation is
used to update
Rejecting the session
- GatewayScript example
-
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 example
-
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>