Scripting Recipes
Small, real scripts you can drop into a rule and tweak. Each one names which phase it goes in (request or response). For the full API surface, see the Scripting API Reference.
Stamp every request with a trace ID
Section titled “Stamp every request with a trace ID”Phase: request. Match: https://api.example.com/*.
pro.request.headers.upsert({ key: 'X-Request-Id', value: pro.crypto.sha256(Date.now() + ':' + Math.random()).slice(0, 16),});Adds a short hex trace ID to every outgoing request so server logs can be cross-referenced with what Probe captured.
Sign a request with HMAC-SHA256
Section titled “Sign a request with HMAC-SHA256”Phase: request. Match: the API host that requires signing.
const ts = Math.floor(Date.now() / 1000).toString();const body = 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.
Decode a JWT and log the payload
Section titled “Decode a JWT and log the payload”Phase: request. Useful when you want to see who an outgoing 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 Probe’s scripting console.
Capture a token from the login response
Section titled “Capture a token from the login response”Phase: response. Match: https://api.example.com/auth/login.
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 stashes it in the active environment so later requests can reference it as {{authToken}}.
Assert response shape
Section titled “Assert response shape”Phase: response. Match: the endpoint you’re testing.
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 scripting console with pass/fail badges.
Mock a 500 error for a percentage of requests
Section titled “Mock a 500 error for a percentage of requests”Phase: request. Forces a percentage of calls to fail so you can exercise the client’s error path.
if (Math.random() < 0.2) { // Reroute the upstream to an endpoint we know returns 500. pro.request.url = 'https://httpstat.us/500'; console.warn('forcing 500 for testing');}20% of matching requests get rewritten to an upstream that always returns 500. To replace a response body in flight without going to a real origin, use Map Local instead.
Replace a JSON field in the response (via Map Local + script)
Section titled “Replace a JSON field in the response (via Map Local + script)”For permanent response edits, Map Local is the right tool — it doesn’t even hit the network. But you can use a response script to log when the field is what you didn’t expect:
pro.test('user is admin', function () { const data = pro.response.json(); pro.expect(data.user.role).to.equal('admin');});Pair this with a Map Local rule that serves the canned admin response, and the test confirms your client behaves correctly when the role flips.
Refresh an expired token mid-flight
Section titled “Refresh an expired token mid-flight”Phase: request. Match: https://api.example.com/*.
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.
Strip cookies for matching requests
Section titled “Strip cookies for matching requests”Phase: request. Useful when you want to test an unauthenticated path without logging out of the browser.
pro.request.headers.remove('Cookie');pro.request.headers.remove('Authorization');Removes the auth headers Probe captured from your browser session for just this rule’s matched requests.
Time a single endpoint
Section titled “Time a single endpoint”Phase: response. Logs the server-reported 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.
Related
Section titled “Related”- Scripting Overview
- Scripting API Reference
- Map Remote — for upstream rewrites you’d otherwise script.
- Breakpoints — for one-off manual edits instead of a scripted rule.