multistep module

The multistep module is used for the service to call a processing rule directly from GatewayScript actions.

To access the API in the multistep module, use the require('multistep') statement, such as var ms = require('multistep');.

ms.callRule()

Calls the named processing rule directly from a GatewayScript action.

Syntax
ms.callRule(rule,input,output,[manager],function(error))
Parameters
rule
The name of the processing rule. The rule name is a string. You cannot specify the name of an API processing rule.
input
The input data that the action processes.
output
The output data that stores the document on completion of the action.
manager
The XML manager to use when you want custom processing. When not specified, processing uses the XML manager settings, if available to the DataPower® service.
function
The asynchronous callback function that runs when the processing rule completes the document processing.
error
The error object when any error occurs during the processing. If no error occurs, the error object is null.
Guidelines
The called processing rule reads documents from the input and writes results to the output.
The rules for setting the input and output parameters vary based on different services.
Traditional services to process GatewayScript actions
Rules for setting the input attribute
The session input context is one of the following values.
  • session.INPUT
  • session.input
  • session.createContext()
  • null that is the NULL context.
Rules for setting the output attribute
The session output context is one the following values. Depending on the rule direction, the output specifies the transmission to the requesting client or responding server.
  • session.output
  • session.createContext()
  • null that is the NULL context.
API gateway service to process GatewayScript assembly actions
Rules for setting the input attribute
The session input context is one of the following values.
  • session.INPUT
  • session.input
  • session.createContext()
  • null that is the NULL context.
  • A string that represents a message object. The payload of the message.body message object is the input data to be processed.

    The headers of the message.headers message object are the input headers to be processed and are the original and initial headers in the called rule. In the called rule, the response headers are the same as the current headers.

    The variables of the message.variables message object are the input variables to be processed and are the variables of the input context of the called rule.

    When the input is an empty string (''), no input is provided.

Rules for setting the output attribute
The session output context is one the following values. Depending on the rule direction, the output specifies the transmission to the requesting client or responding server.
  • session.output
  • session.createContext()
  • null that is the NULL context.
  • A string that represents a message object. The payload of the message.body message object stores the output data.

    The headers of the message.headers message object store the output headers.

    The variables of the message.variables message object store the variables of the output context of the called rule.

    When the output is an empty string (''), no output is stored.
    • The output cannot be any read-only variables in the API context.
    • If the payload of the output exists, delete it first.
Examples
  • Call ruleMPGW from the GatewayScript action in the Multi-Protocol Gateway processing policy.
    var ms = require('multistep');
    ms.callRule('ruleMPGW', session.input, session.output, function(error) { 
      if (error) { 
        throw error;
      }
    });
  • Call ruleAPIGW from the GatewayScript assembly action in the API gateway assembly. foo and bar are message objects.
    var ms = require('multistep');
    
    var fooObj = context.createMessage('foo');
    var barObj = context.createMessage('bar');
    
    fooObj.body.write('HelloWorld');
    fooObj.header.set('Header1', 'myHeader');
    fooObj.setVariable('Var1', 'myVar');
    
    ms.callRule('ruleAPIGW', 'foo', 'bar', function(error) {
      barObj.body.readAsBuffer(function(error, buf) {
        var OutputPayload = buf.toString();
        var OutputHeaders = barObj.header.get();
        var OutputVar1 = barObj.getVariable('Var2');
      });
    });

ms.callRuleWrapperInit()

This helper function initializes global variables that the callRuleWrapper() function requires. When not called, it is called internally before the callRuleWrapper() processing starts.This function determines whether this invocation is within an API gateway user-defined policy (UDP). When within an API gateway UDP, this function gets the UDP policy properties and places them into the provided properties options object. For API gateway UDPs, this function determines the name of the default rule and places it into the options object if one is not currently present.
Note: For GatewayScript actions that are not UDP, any properties that the called rule needs and the called rule name itself must be explicitly provided in the options object.
Syntax
ms.callRuleWrapperInit()
Guidelines
The ms.callRuleWrapperInit() function returns a JSON object that contains a custom console object and a verbose Boolean.
The custom console object
The custom console object sets the log category.
  • For API gateway services, the apiconnect category.
  • For traditional services, the gatewayscript category.
The verbose Boolean
The verbose Boolean is true in the following situations.
  • For API gateway services, the request contains the APIm-Debug request header set to true or the API probe is enabled.
  • For traditional services, the request contains either the APIm-Debug or the verbose request header set to true.
Use the verbose Boolean to wrap any nonerror message that the code might use that follows the use of this function, which includes within any callback function that you developed.
let debugObj = ms.callRuleWrapperInit(options);
if (debugObj.verbose) {
  debugObj.console.debug(`${options.ruleName} is called.`);
}

ms.callRuleWrapper()

This function uses an options object to direct specific behaviors of the module, runs the processing rule, and handles responses. A callback function is supported that supplies an error object to indicate that an error occurred during processing. The error object is null when no error occurred.

Syntax
ms.callRuleWrapper(options[,callback(function(error){}])
Parameters
options
The options object is provided as the only mandatory argument. The options object specifies the following details.
  • The name of the processing rule to call
  • Input message processing
    • The input body and headers to use
    • How to read the input body
    • How to pass input headers
  • Output message processing
    • Where to save any output body and headers
    • How to read the called rule response body
    • How the called rule response headers are to be saved
  • Callback function references
  • A properties object to provide to the called rule
When within an API gateway user-defined policy (UDP), you can include properties that are not disclosed to the API developer who use the UDP. The initialization function adds to these properties the policy properties that are disclosed to the API developer. When not within an API gateway UDP, the developer must specify all the properties that need to be passed to the called rule. The options schema is as follows.
{
  "ruleName": "calledRuleName",
  "input": {
    "name": "message",
    "read_body": true | false,
    "body_type": "json" | "xml" | "buffer",
    "headers": "none" | "set" 
  },
  "output": {
    "name": "message",
    "read_body": true | false,
    "update_body": true | false,
    "body_type": "json" | "xml" | "buffer",
    "headers": "none" | "set" | "merge"
  },
  "callbacks": {
    "pre_call": validateInput,
    "post_call": handleoutput,
    "post_error": null
  }
  "properties": {
    "name": "value"
  }
}
"ruleName": "calledRuleName"
The name of the processing rule to call. For API gateway UDPs, the callRuleWrapperInit() helper function adds the name of the default rule automatically when not in the options object.
"input":{}
"name": "message"
The input data that the action processes.
  • For API gateway services, specify the message context. With message as the name, the input payload can be retrieved from message.body and input headers from message.headers.
  • For traditional services, specify the session context such as INPUT. Contexts of PIPE, NULL, and OUTPUT are not allowed.
"read_body": true | false
The option to read the message body from the input data. Use true to read or false to ignore. The default value is false.
"body_type": "json" | "xml" | "buffer"
The option on how to read the message body from the input data. The data is read with the appropriate readAs<type> function. Valid values are json, xml, or buffer. The default value is buffer.
"headers": "none" | "set"
The option of which message headers from the input data to marshal to the called rule. Valid values are none and set. The default value is none.
Note: This option applies to only API gateway use cases. Traditional services use the same header-metadata, without a need to marshal.
"output":{}
"name": "message"
The output data that stores the document on completion of the action.
  • For API gateway services, specify the message context. With message as the name, the output payload of the called rule can be written to message.body and output headers to message.headers.
  • For traditional services, specify the session context such as myContext. Contexts of PIPE, NULL, and OUTPUT are not allowed.
"read_body": true | false
The option to read the output from the called rule. Use true to read or false to ignore. The default value is false.
"update_body": true | false
The option to update the message body with the body of the called rule when an output name is provided and read. Use true indicate to update the message body. Use false when the update is in the post_call callback. The default value is true.
"body_type": "json" | "xml" | "buffer"
The option on how to read the message body from the called rule. The data is read with the appropriate readAs<type> function. Valid values are json, xml, or buffer. The default value is buffer.
"headers": "none" | "set" | "merge"
The option to marshal message headers from the called rule. Valid values are none, set, and merge. The default value is none.
  • When set, replace existing output headers.
  • When merge, augment existing output headers.
Note: This option applies to only API gateway use cases. Traditional services use the same header-metadata, without a need to marshal.
"callback":{}
"pre_call": function
The callback function to validate the message body in the input data and do any preprocessing. Without a callback, validation is assumed to be successful and the rule is called. The sample schema shows the validateInput function. For more information, see pre_call() callback for ms.callRuleWrapper().
"post_call": function
The callback function to validate the message body in the output data. This function can update the output body of the called rule and update the body of the output message directly. The sample schema shows the handleOutput function. For more information, see post_call() callback for ms.callRuleWrapper().
"post_error": function
The callback function to override default error handling. The sample schema shows null, which indicates no processing change. For more information, see post_error() callback for ms.callRuleWrapper().
function
The asynchronous callback function that runs when the processing rule completes the document processing.
error
The error object when any error occurs during the processing. If no error occurs, the error object is null.
Example
The ms.callRuleWrapper() function that uses the async callback function. In the else clause, you can define any additional processing, which can include another call to the ms.callRuleWrapper() function after you provide another options object for the next rule to call.
ms.callRuleWrapper(options, function(error) {
  if (error) {
    console.error(`${options.ruleName} ${error.errorMessage}`);
  } else {
    console.info(`Called rule ${options.ruleName} completed successfully`);
  }
});

pre_call() callback for ms.callRuleWrapper()

This callback function validates the body of the input message. The function name can be any function that you wrote. When you do not need a pre_call callback function, omit this property from the options object or configure this property with the null value. When configured, this function returns a Boolean true to indicate successful validation. If any issue is found with the input data, this function returns a Boolean false to halt processing.

For example, this callback function can implement the following behaviors.
  • Make sure that the payload is XML in the called rule.
    • Make sure that the inBody argument is an XML data type.
    • Make sure that the Content-Type header indicates that the payload is XML.
  • Validate that certain XML elements or JSON properties are present.
  • Create specific context variables that the called rule needs.
Signature
pre_call(options,contextMsg,inHeaderObject,inCalledRuleHeaderObject,inBody)
Arguments
options
The options object.
contextMsg
The context of the input message.
inHeaderObject
The header object for the input message context. You can use the get function to retrieve specific response headers.
  • For API gateway services, retrieves context.message.header.
  • For traditional services, retrieves header-metadata.current.
inCalledRuleHeaderObject
The header object to send to the called rule. You can use the set function to add or update request headers to send to the called rule.
  • For API gateway services, adds or updates context.internalName.header.
  • For traditional services, adds or updates header-metadata.current.
inBody
The input data from the input message that was read by using the input options. This data can be from the input or undefined when the input context name is not present in the options or the output read_body option is false. The value of the input.body_type option determines the data type of the input as buffer, JSON object, or XML document.
Response
The response is based on the return statement in the function. The Boolean indicates whether the error causes the transaction to be rejected. Without a return statement, the function always returns a Boolean false.
Example
/*
* validateInput   - User-written function to inspect the payload of the input message to make sure that
*                   it is present and the the Content-Type header indicates that the payload is JSON.
* @options        - The options object.
* @contextMsg     - The context of the input message.
* @contextHdrs    - The context header object of the input message, which is used to retrieve the 
*                   Content-Type header.
* @calledRuleHdrs - The input headers object of the called rule, which is used to set or update headers
*                   to send to the called rule.
* @inBody         - The input json object to read from the input message.
* 
* @return         - A boolean that indicates whether the input is valid and processing can continue.
*/
function validateInput(options, contextMsg, contextHdrs, calledRuleHdrs, inBody){
  let isValid = false;
  if (inBody) {
    // Consider the payload valid and pass to the processing when when both conditions met.
    // - The input context has a payload body.
    // - The Content-Type header is also JSON.
    let contentType = contextHdrs.get('Content-Type');
    if (session._isAssemblyAction) {
      if (context.isJSON(contentType)) {
        isValid = true;
      }
    } else {
      // Traditional services session object does not have an isJSON function. Instead, use a string function.
      if (contentType.includes('json')) {
        isValid = true;
      }
    }
  }
  return isValid;
}

post_call() callback for ms.callRuleWrapper()

This callback function overrides the default module behavior with the output of the called rule. The function name can be any function that you wrote. When you do not need a post_call callback function, omit this property from the options object or configure this property with the null value. When configured, this function returns a Boolean true to accept the response payload. If any issue is found with the output data, this function returns a Boolean false to halt processing.

The default module behavior is to update the body of the context message with how the output of the called rule is read with the output.body_type option.

Signature
post_call(options,contextMsg,outHeaderObject,outCalledRuleHeaderObject,outBody)
Arguments
options
The options object.
contextMsg
The context of the output message.
outHeaderObject
The header object for the output message context. You can use the set function to add or update output headers.
  • For API gateway services, adds or updates context.message.header.
  • For traditional services, adds or updates header-metadata.current.
outCalledRuleHeaderObject
The header object for the output message of the called rule. You can use the get function to retrieve specific response headers from the called rule.
  • For API gateway services, retrieves context.internalName.header.
  • For traditional services, retrieves header-metadata.current.
outBody
The output data from the called rule that is read. This data can be from the output of the called rule or undefined when the output context name is not present in the options or the output read_body option is false. The value of the output.body_type option determines the data type of the output as buffer, JSON object, or XML document.
Response
The response is based on the return statement in the function. The Boolean indicates whether the body of the output body is valid and processing continues. Without a return statement, the function always returns a Boolean false.
Example
// Assuming the code already processed...
let debugObj = ms.callRuleWrapperInit(options);

/*
* handleCalledRuleOutput - User-written function for this policy. In the case there is an error when reading the
*                          output payload of the called rule, do nothing. With output payload, write this payload
*                          to the body of the context message to become a parsed XML document.
* @options               - The options object.
* @contextMsg            - The context of the output message to write the body to the context, if wanted.
* @contextHdrs           - The output headers object to update the Content-Type header of the message.
* @calledRuleHdrs        - The output headers object of the called rule to retrieve the headers from the called rule.
* @outBody               - The output of the called rule as an XML document from the output.body_type option.
* 
* @return                - A boolean that indicates whether the output is valid and processing can continue.
*/
function handleCalledRuleOutput(options, contextMsg, contextHdrs, calledRuleHdrs, outBody) {
  let isValid = false;
  // No output name is validation that the JSON is well formed but there is no body.
  // Read.
  if (!options.output.name) {
    isValid = true;
  } else if (outBody) {
    // Can perform some validation of the XML before setting a true return value.
    isValid = true;
    if (debugObj.verbose) {
      debugObj.console.info(`${options.ruleName} post call: output: ${XML.stringify(outBody)}`);
    }
    // Handle service-specific updates of the message body when the output option for update_body is false.
    // The callback must handle the updates.
    if (session._isAssemblyAction) {
      contextMsg.body.write(outBody);
    } else {
      contextMsg.write(outBody);
    }
    contextHdrs.set('Content-Type', 'application/xml');
    calledRuleHdrs.set('testing-postcall-hdr', 'hello world');
  }
  return isValid;
}

post_error() callback for ms.callRuleWrapper()

This callback function provides custom error handling when the called rule fails during processing. The function name can be any function that you wrote. When you do not need a post_error callback function, omit this property from the options object or configure this property with the null value. When configured, this function can override the HTTP status code, reason phrase, and description for an error. When configured, this function returns a Boolean true to continue error processing with any updated error information or false to not generate an error. When this function returns a Boolean false, the caller of the callRuleWrapper() function receives no error.

For example, the exception for an AAA error is either errorSubcode 0x01d30001 or 0x01d30002 and a 401 Forbidden HTTP return code. You can override to return 401 Unauthorized or not reject the transaction. To not reject the transaction, return a Boolean of false. Otherwise, return a Boolean of true to reject the transaction with the status information from the updated error object.

Signature
post_error(options,error,errorCode,errorSubcode)
Arguments
options
The options object.
error
The error object for the called rule.
errorCode
The DataPower error code for the failed called rule.
errorSubcode
The DataPower suberror code for the failed called rule.
Response
The response is based on the return statement in the function. The Boolean indicates whether the error causes the transaction to be rejected. Without a return statement, the function always returns a Boolean false.
Example
/*
* handleError   - User-written function for the Kerberos validation policy to provide custom error handling.
* @options      - The consolidated options object. The API can provide unique options.
* @error        - The error object for the called rule.
* @errorCode    - The DataPower error code for the called rule that failed.
* @errorSubcode - The DataPower suberror code for the called rule that failed.
* 
* @return       - A boolean that indicates whether to reject the transaction.
*/
function handleError(options, error, errorCode, errorSubcode) {
  // Set the error code and reason phrase and return a Boolean to cause the policy to fail.
  switch (errorSubcode) {
  case '0x01d30002':
    error.errorStatusCode = 401;
    error.errorPhrase = "Unauthorized";;
    error.errorName = "UnauthorizedError";
    if (!error.errorMessage) error.errorMessage = '';
    break;
  default:
    error.errorStatusCode = 500;
    error.errorPhrase = "Internal Server Error";;
    error.errorName = "RuntimeError";
    if (!error.errorMessage) error.errorMessage = '';
    break;
  }
  return true; // The actual setting of the HTTP status code or reason. The potential reject is done by the framework.
}