Request and Response Transforms
Change outbound requests and inbound responses with sandboxed TypeScript or JavaScript
Request and Response Transforms
Transforms let you run small TypeScript or JavaScript functions inside a RequestRocket proxy. Use them when a target API needs a different request shape, or when callers need a normalized response shape.
RequestRocket supports two transform types:
- Request transforms run after proxy overrides and before RequestRocket sends the request to the target API.
- Response transforms run after payload filters and before the response is returned or recorded.
Transform code runs in a restricted QuickJS sandbox. It cannot use network access, filesystem access, npm modules, environment variables, process, fetch, require, or imports.
How Transforms Work
Transforms are attached to a proxy. Each transform can either run for every request, or only when its predicates match the current request or response.
Only one request transform and one response transform are selected for each request. When multiple active transforms match, the highest priority value wins.
When To Use Transforms
Use request transforms to:
- Rename request fields before forwarding to the target.
- Add target-specific headers, query parameters, or body fields.
- Convert a caller-friendly payload into a legacy target format.
Use response transforms to:
- Normalize different upstream response formats into one consistent schema.
- Add response metadata for callers.
- Rename or reshape fields after filters have removed data.
For simple fixed additions to every request, use proxy overrides first. Use transforms when the change needs code, branching, or payload restructuring.
Minimum Transform Code
A transform must export a default function or async function. The function can return either an object or a JSON string.
Request no-op
export default async function transform(proxyContext, proxyRequest) {
return proxyRequest;
}The returned object can modify headers, params, data, and url (as a relative path). All other fields are ignored; they are controlled by the platform and cannot be changed from a transform. Returning the provided proxyRequest unchanged is the safest no-op request transform.
Response no-op
export default async function transform(proxyContext, proxyRequest, targetResponse) {
return targetResponse;
}The returned response object must include a numeric status. Returning the provided targetResponse unchanged is the safest no-op response transform.
Runtime Inputs
RequestRocket injects these values into your transform function.
| Argument | Available In | Description |
|---|---|---|
proxyContext | Request and response transforms | Proxy metadata such as proxyId, proxyName, proxyRegion, clientId, method, and path |
proxyRequest | Request and response transforms | The Axios-style request configuration being sent to the target |
targetResponse | Response transforms | The Axios-style target response after filters have been applied |
proxyRequest contains:
{
method: string; // locked — cannot be changed
url: string; // the relative path only (e.g. "/items/123") — you may rewrite this; must stay a relative path
headers: Record<string, string>; // editable — deny-listed and auth headers are enforced by the platform
params?: Record<string, string>; // editable query parameters
data?: unknown; // editable request body (POST / PUT / PATCH only)
}Fields not listed above (baseURL, method, timeout, validateStatus, etc.) are platform-controlled and are ignored even if your transform returns them. The base URL of the target is intentionally hidden from transform code.
targetResponse contains:
{
status: number;
statusText: string;
headers: Record<string, string>;
data: unknown;
}Creating A Request Transform
Open The Proxy
Go to Proxies, select the proxy, then open Request Transforms.
Create A Transform
Choose whether the transform is active, whether it should apply to all requests or conditional matches, and set a priority.
Write The Code
For example, add a target-specific header and reshape the body:
export default async function transform(proxyContext, proxyRequest) {
return {
...proxyRequest,
headers: {
...proxyRequest.headers,
"x-source-system": "requestrocket"
},
data: {
customer_id: proxyRequest.data?.customerId,
plan_code: proxyRequest.data?.plan
}
};
}Save
RequestRocket validates the code before saving it. If validation passes, the transform is stored and becomes available immediately.
Creating A Response Transform
Response transforms receive the final filtered target response. For example, normalize a target response into a caller-facing shape:
export default async function transform(proxyContext, proxyRequest, targetResponse) {
return {
...targetResponse,
data: {
id: targetResponse.data?.customer_id,
name: targetResponse.data?.display_name,
status: targetResponse.data?.account_status
}
};
}Conditional Transforms
Set transformMode to conditional when a transform should only apply to some traffic. Conditional transforms can match request data such as method, path, query parameters, headers, body fields, and JWT claims.
Response transforms can also match response data such as response headers, response body fields, and response status.
Use effect to decide how matches are interpreted:
includeapplies the transform when the predicates match.excludeapplies the transform when the predicates do not match.
Static Validation
The Core API and dashboard reject transform code before it is saved if it fails the minimum static checks.
Validation requires:
- Non-empty TypeScript or JavaScript under 512 KB.
- A callable
export default. - No
import, re-export, dynamic import, orrequire. - No references to unsupported sandbox globals such as
process,global,globalThis,fetch,XMLHttpRequest,WebSocket,Deno,Bun,eval, orFunction.
Static validation catches unsupported code shape early. Runtime validation still checks the returned object after the transform executes.
Security Contract
RequestRocket enforces strict boundaries on what a transform can and cannot change. These protections exist to prevent credential leakage, request routing attacks, and misconfiguration that could break the proxy pipeline.
What request transforms CAN modify
| Field | Rules |
|---|---|
headers | You can add or change custom headers. However, headers on the platform deny-list and authentication headers are always stripped before the request is sent (see below). |
params | You can add, change, or remove query parameters freely. |
data | You can reshape the request body. Only applied for POST, PUT, and PATCH methods. |
url | You can rewrite the relative path (e.g. /v1/items to /v2/items). Must remain a relative path — absolute URLs are rejected. |
What request transforms CANNOT modify
These fields are controlled by the platform and are ignored if your transform returns them:
| Field | Why |
|---|---|
baseURL | The target's base URL is locked to the configured target and is never exposed to transform code. |
method | The HTTP method is locked to the caller's original method. |
timeout | Controlled by the platform to prevent gateway timeouts. |
validateStatus | RequestRocket never throws on HTTP status codes — the caller handles status codes. |
responseType | Locked to arraybuffer for binary data integrity. |
maxRedirects | Locked to 0 — the proxy never auto-follows redirects; the caller receives 3xx responses directly. |
paramsSerializer | Automatically selected based on whether final query parameters contain OData $ prefixes. |
| Any other Axios config field | Fields such as proxy, httpAgent, httpsAgent, adapter, socketPath, auth, or beforeRedirect are always ignored. |
Returning an absolute URL (e.g. https://example.com/path or //example.com/path) in the url field will cause the request to be hard-rejected with a transform-invalid-output error. This prevents credential exfiltration to arbitrary hosts.
Header governance
RequestRocket enforces a platform header deny-list. These headers are always removed from the final request, regardless of whether they come from the caller, a proxy override, or your transform:
- Authentication:
Authorization,x-api-key - Routing / method override:
Host,x-http-method-override,x-method-override,x-original-url,x-rewrite-url,x-forwarded-host,forwarded,x-forwarded-server,x-host - Hop-by-hop:
Connection,Keep-Alive,Transfer-Encoding,Upgrade,Via,Proxy-Authenticate,Proxy-Authorization,TE,Trailer - Forwarding / infrastructure:
x-forwarded-for,x-forwarded-proto,x-forwarded-port,Content-Length - AWS / CloudFront:
x-amzn-trace-id,x-amz-cf-pop,x-amz-cf-id,cloudfront-*headers
Authentication headers are injected exclusively by the configured target credential after your transform runs. A transform cannot inject its own authentication — the credential always wins.
Header names and values must be plain strings. Headers containing control characters (CR/LF) are rejected with a transform-invalid-output error to prevent header injection attacks.
What response transforms CAN see
Response transforms receive:
- The
proxyRequestobject with headers and params sanitised (authentication material is never visible). - The
targetResponseafter payload filters have been applied.
Response transforms CAN modify status, headers, and data on the response.
What response transforms CANNOT see
- The target credential or any injected authentication headers/params.
- The target base URL.
- Internal Axios configuration fields.
Sandbox Limits
Each transform runs with:
- 5 second execution timeout.
- 32 MB memory limit.
- No network access.
- No filesystem access.
- No npm module access.
- No access to AWS SDK, environment variables, or the Node.js process.
RequestRocket always removes authentication and infrastructure headers from the request object before passing it to the sandbox.
Runtime Errors
When a transform fails at runtime, RequestRocket returns a structured error response with transform-specific headers.
| Header | Value |
|---|---|
requestrocket-proxy-code | transform-error |
requestrocket-proxy-error | request-transform-failed or response-transform-failed |
requestrocket-proxy-message | Sanitized failure message |
Most transform failures return 422. Memory limit failures return 500.
Response body:
{
"error": "request-transform-failed",
"message": "Transform output does not conform to the expected request structure",
"code": "transform-invalid-output"
}Possible error codes are:
transform-errortransform-timeouttransform-memory-exceededtransform-invalid-output
Sync And Async APIs
Transforms run for both Proxy API requests and Async API requests. The same proxy transform configuration is used by both paths, so test transform changes against whichever API mode your integration uses.
Best Practices
- Keep transforms small and deterministic.
- Return a complete request or response object, not just the fields you changed.
- Avoid storing secrets in transform code — use the credential configuration for authentication.
- Use payload filters for redaction and transforms for shape changes.
- Use conditional predicates instead of branching on every request inside the code when possible.
- Express query parameters via
paramsrather than appending them to theurlpath. - Never attempt to set authentication headers in your transform — they will be stripped. Configure credentials through the target credential settings instead.
- If you need to rewrite the path, keep it relative (e.g.
/api/v2/resource). Do not include the scheme or host.