Configuring and Using Scripting
Overview
Scripting makes it possible to extend API Simulator with functionality that’s not yet built-in. |
Scripting vs. Scriptlets
Scripts can be used in matchers, parameters, and placeholders definitions. Such scripts get access to the execution context (the _context
variable), and through that, to any parameter. Scripts can call functions defined in external libraries or can themselves define custom functions and methods. Out-of-the-box there is support for the JavaScript and Groovy scripting languages. Historically, scripts have been a feature of API Simulator pretty much since the beginning.
In contrast, scriptlets currently can only be used in a Simula template to produce output and to control logic (if…else, loops, etc.). The scripting language supported for scriptlets is Groovy.
Script Executor
Executing a script is via a…script executor. There are two possible ways to configure one - a separate, reusable instance of the script executor, or script executor specific to a script. The script executors are thread-safe so it is possible to define them outside of any script object - that will result in faster simulation startup time and reduced memory utilization.
ScriptExecutorName:
is: scriptExecutor
lang: javascript | groovy
# Optional list of directories with script libraries
libs:
- "<directory1 with script libraries>"
#...
- "<directoryN with script libraries>"
The libs
list elements can be absolute file paths, or paths with respect to the directory of the simulation or the directory with all simlets given by the global variables ${sim.path}
and ${simlets.path}
, respectively.
If a script doesn’t have script executor defined, then the script executor is assumed to be Groovy script executor and that it is specific to the script.
Scripts
JavaScript
#...
CardNumber:
is: parameter
from: body
element: ".payer.funding_instruments[0].credit_card.number"
#...
JavascriptExecutor:
is: scriptExecutor
lang: javascript
libs:
- "${sim.path}/scripts"
maskCardNumberScript1:
is: script
# Reference to a reusable script executor instance
executor: JavascriptExecutor
# Call a function declared in an external library
expression: "maskCardNumber('CardNumber', 'x', 4)"
maskCardNumberScript2:
is: script
# Script executor specific to this script
executor:
lang: javascript
libs:
- "${sim.path}/scripts"
expression: "maskCardNumber('CardNumber', 'x', 4)"
Groovy
#...
CardNumber:
is: parameter
from: body
element: ".payer.funding_instruments[0].credit_card.number"
#...
GroovyScriptExecutor:
is: scriptExecutor
lang: groovy
libs:
- "${sim.path}/scripts"
maskCardNumberScript1:
is: script
# Reference to a reusable script executor instance
executor: GroovyScriptExecutor
expression: "maskCardNumber('CardNumber', 'x', 4)"
maskCardNumberScript2:
is: script
# Script executor specific to this script. Optional.
executor:
lang: groovy
libs:
- "${sim.path}/scripts"
expression: "maskCardNumber('CardNumber', 'x', 4)"
Script Expression
The expression
can reference a function/method defined in a script library or it can contain the actual code. Notice the indentation of the script’s code in this contrived example:
# Multi-line inlined script
padZip5Plus4Script:
is: script
executor: javascriptExecutor
expression: |
function padZipCode() {
var zipCode = '' + _context.get('BillingAddressPostalCode');
if (zipCode && zipCode.length == 5) {
zipCode = zipCode + '-0000';
}
return zipCode;
}
padZipCode();
Scripted Parameters
Scripted Parameters are parameters which values are the result from executing a script. API Simulator supports the JavaScript and Groovy scripting languages.
Notice that a similar result can be achieved using Groovy scripting in an eval
expression.
Here is an example of a scripted parameter:
request:
# ....
# Matcher for a Parameter
- where: parameter
named: ProfileID
equals: "Profile-123"
# A parameter with all the cookies
HttpCookies:
is: parameter
from: header
named: "Cookie"
# This parameter value is the results from executing a script.
# Notice that what the script does - extracting a cookie by
# name - is just for demo purposes. This is much easier using
# the built-in support for parameters from cookies.
ProfileID:
is: parameter
from: script
executor:
# 'groovy' is also supported as the scripting language
lang: javascript
expression: |-
function getCookieValue(name)
{
// The value from the context is an object so must convert it to string
var cookies = "" + _context.getValue('HttpCookies');
// The rest of the code is from https://www.quirksmode.org/js/cookies.html
var nameEQ = name + "=";
var ca = cookies.split(';');
for(var i=0;i < ca.length;i++) {
var c = ca[i];
while (c.charAt(0)==' ') c = c.substring(1,c.length);
if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
}
return null;
}
getCookieValue("profile_id");
# ...
Scripted Matchers
The support for Scripted Matchers is through matcher for scripted parameter. See the example in the Scripted Parameters section.
Script Results Placeholders
In the following simlet configuration excerpt, MaskedCardNumber
is a parameter used in a placeholder for the result from executing a script:
GroovyScriptExecutor:
is: scriptExecutor
lang: groovy
libs:
- "${sim.path}/scripts"
# This calls a function defined in an external script
MaskCardNumberScript:
is: script
executor: GroovyScriptExecutor
expression: "maskCardNumber('x', 4)"
MaskedCardNumber:
is: parameter
from: script
script: "MaskCardNumberScript"
response:
from: template
template: Simula
status: 201
headers:
- "Content-Type: application/json; charset=UTF-8"
body: |+
{
...
"funding_instruments": [
{
"credit_card": {
...
"number": "${MaskedCardNumber}",
...
}
}
]
}
See also the scripting examples included in the Standalone API Simulator’s distro.
We would love to hear your feedback! Shoot us an email to [feedback at APISimulator.com] about anything that is on your mind.
Happy API Simulating!