Skip to content

Scripting Recipes

Small, real scripts you can drop in and tweak. The first set are script rules: they rewrite live traffic with handleRequest / handleResponse (see the Scripting Overview). The second set use the pro API, which runs in Composer pre-request and test scripts and in Flow script nodes (see the Scripting API Reference).

Phase: request. Match: api.example.com/*.

function handleRequest(request) {
request.headers['X-Request-Id'] = Math.random().toString(16).slice(2, 18);
return request;
}

Adds a short hex trace ID to every outgoing request so server logs can be cross-referenced with what Probe captured.

Phase: request. Useful when you want to test an unauthenticated path without logging out of the browser.

function handleRequest(request) {
for (const name of Object.keys(request.headers)) {
const lower = name.toLowerCase();
if (lower === 'cookie' || lower === 'authorization') delete request.headers[name];
}
return request;
}

Removes the auth headers from this rule's matched requests only.

Send a share of requests to an error endpoint

Section titled “Send a share of requests to an error endpoint”

Phase: request. Forces a percentage of calls to fail so you can exercise the client's error path.

function handleRequest(request) {
if (Math.random() < 0.2) {
// Reroute the upstream to an endpoint we know returns 500.
request.url = 'https://httpstat.us/500';
}
return request;
}

20% of matching requests get rewritten to an upstream that always returns 500. To serve a canned response without going to a real origin, use Map Local instead.

Phase: response. Match: api.example.com/v1/me.

function handleResponse(request, response) {
const data = JSON.parse(response.body || '{}');
data.user.role = 'admin';
response.body = JSON.stringify(data);
return response;
}

Your client sees role: "admin" while the server still answered with the real value. For a fully canned body, Map Local doesn't even hit the network.

Where: a Composer pre-request script.

const ts = Math.floor(Date.now() / 1000).toString();
// The script sees the body before {{variables}} are resolved: sign what is sent.
const body = pro.variables.replaceIn(pro.request.body.raw || '');
const secret = pro.environment.get('apiSecret');
const sig = pro.crypto.hmacSha256(ts + body, secret);
pro.request.headers.upsert({ key: 'X-Timestamp', value: ts });
pro.request.headers.upsert({ key: 'X-Signature', value: sig });

Signs the timestamp + body with a secret pulled from the environment, attaching both as headers to the request that goes out.

Where: a Composer pre-request script. Useful when you want to see who a call is authenticating as.

const auth = pro.request.headers.get('Authorization') || '';
const token = auth.replace(/^Bearer\s+/i, '');
if (token) {
const decoded = pro.crypto.jwtDecode(token);
console.log('sub:', decoded.payload.sub, 'exp:', decoded.payload.exp);
}

Logs the sub and exp claims of the bearer token to the Composer script console.

Where: the test script of your login request in Composer.

if (pro.response.code === 200) {
const token = pro.response.json().accessToken;
pro.environment.set('authToken', token);
console.log('captured authToken (' + token.length + ' chars)');
}

Pulls the accessToken out of the login response and saves it as the current value of authToken in the active environment, so later requests can reference it as {{authToken}}.

Where: a Composer test script, or a Flow script assertion.

pro.test('status is 200', function () {
pro.expect(pro.response.code).to.equal(200);
});
pro.test('content type is JSON', function () {
pro.expect(pro.response.headers.get('Content-Type')).to.contain('application/json');
});
pro.test('body has the right shape', function () {
pro.expect(pro.response.json()).to.have.jsonSchema({
type: 'object',
required: ['userId', 'email'],
properties: {
userId: { type: 'integer' },
email: { type: 'string' },
},
});
});

Three independent test blocks — failures in one don't hide the others. Results show up in the Composer test results with pass/fail badges.

Where: a Composer pre-request script (or the collection's).

const token = pro.environment.get('authToken');
const exp = parseInt(pro.environment.get('authExp') || '0', 10);
const nowSec = Math.floor(Date.now() / 1000);
if (!token || nowSec >= exp) {
const res = pro.sendRequest({
url: 'https://api.example.com/auth/refresh',
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ refreshToken: pro.environment.get('refreshToken') }),
});
if (res.code === 200) {
const body = res.json();
pro.environment.set('authToken', body.accessToken);
pro.environment.set('authExp', String(nowSec + body.expiresIn));
pro.request.headers.upsert({ key: 'Authorization', value: 'Bearer ' + body.accessToken });
} else {
console.error('refresh failed:', res.code, res.status);
}
}

Checks an expiry stored in the environment, calls the refresh endpoint synchronously via pro.sendRequest, then attaches the fresh token to the original request before it goes out. Up to 5 sub-requests per execution are allowed.

Where: a Composer test script. Logs the response time only when it crosses a threshold.

if (pro.response.responseTime > 500) {
console.warn(
pro.info.requestName,
'took',
pro.response.responseTime + 'ms',
'(>' + 500 + 'ms threshold)',
);
}

Quiet most of the time, noisy when the endpoint is slow.