RequestRocketRequestRocketDocs
Guides

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.

ArgumentAvailable InDescription
proxyContextRequest and response transformsProxy metadata such as proxyId, proxyName, proxyRegion, clientId, method, and path
proxyRequestRequest and response transformsThe Axios-style request configuration being sent to the target
targetResponseResponse transformsThe 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:

  • include applies the transform when the predicates match.
  • exclude applies 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, or require.
  • No references to unsupported sandbox globals such as process, global, globalThis, fetch, XMLHttpRequest, WebSocket, Deno, Bun, eval, or Function.

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

FieldRules
headersYou 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).
paramsYou can add, change, or remove query parameters freely.
dataYou can reshape the request body. Only applied for POST, PUT, and PATCH methods.
urlYou 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:

FieldWhy
baseURLThe target's base URL is locked to the configured target and is never exposed to transform code.
methodThe HTTP method is locked to the caller's original method.
timeoutControlled by the platform to prevent gateway timeouts.
validateStatusRequestRocket never throws on HTTP status codes — the caller handles status codes.
responseTypeLocked to arraybuffer for binary data integrity.
maxRedirectsLocked to 0 — the proxy never auto-follows redirects; the caller receives 3xx responses directly.
paramsSerializerAutomatically selected based on whether final query parameters contain OData $ prefixes.
Any other Axios config fieldFields 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 proxyRequest object with headers and params sanitised (authentication material is never visible).
  • The targetResponse after 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.

HeaderValue
requestrocket-proxy-codetransform-error
requestrocket-proxy-errorrequest-transform-failed or response-transform-failed
requestrocket-proxy-messageSanitized 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-error
  • transform-timeout
  • transform-memory-exceeded
  • transform-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 params rather than appending them to the url path.
  • 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.

Next Steps

On this page