Policy name |
JavaScript Scripting |
Summary |
Runs a user-supplied JavaScript module to inspect and modify requests and responses |
Category |
Transformation |
First Omni Gateway version available |
1.14.0 |
Release Notes |
|
Returned Status Codes |
|
Summary
The JavaScript Scripting policy runs a JavaScript module that you supply to inspect and modify HTTP traffic as it passes through the gateway. Use the policy to add or change headers, transform request or response bodies, and block a request with an early response.
The module runs as a standard JavaScript ES module and can export either or both of these functions:
-
requestFilter(request)runs for every incoming request. It can read and modify the request, allow the request to continue to the upstream service, or terminate the request with an immediate response. -
responseFilter(response, requestData)runs for every upstream response. It can read and modify the response before the gateway returns it to the client.
The module must export at least one of these functions to properly load.
Module-level variables persist across invocations to share state between requests (for example, to maintain a counter). The runtime provides the standard console, TextEncoder, and TextDecoder globals. The script runs synchronously; async functions and promises returned from a filter aren’t awaited.
Configure Policy Parameters
Omni Gateway Local Mode
- policyRef:
name: javascript-scripting-flex
config:
script: <string> // REQUIRED - JavaScript ES module source
| Parameter | Required | Default Value | Description |
|---|---|---|---|
|
Required |
— |
The full source text of a JavaScript ES module. The module must export at least one of |
Script API
The gateway calls the exported functions and passes objects that represent the request or response. These objects can’t be constructed from JavaScript.
Filter Functions
| Function | Description |
|---|---|
|
Called for each incoming request. Receives a |
|
Called for each upstream response. Receives a |
Request and Response Objects
Both the request and response objects expose the same methods to read and modify headers and the body:
| Method | Description |
|---|---|
|
Returns all headers as an array of |
|
Replaces all headers with the provided array of |
|
Returns the value of the first header matching |
|
Sets a header, replacing any existing values for that name. |
|
Appends a header, preserving any existing values for that name. |
|
Removes all headers matching |
|
Returns the body as a |
|
Replaces the body with the provided |
|
Returns the body decoded as a UTF-8 string. Invalid byte sequences are replaced with the Unicode replacement character ( |
|
Replaces the body with the UTF-8 encoding of the provided string. Throws an error if the entity has no body or if the encoded body exceeds the 1 MiB maximum. |
|
Returns |
Controlling Request Flow
The value that requestFilter returns controls whether the request continues:
-
Return
undefinedor{ flow: "continue" }to allow the request to continue to the upstream service. -
Return
{ flow: "continue", data: <value> }to continue and passdatatoresponseFilter. TherequestDataargument ofresponseFilterreceives{ flow: "continue", data: <value> }. -
Return
{ flow: "break", response: { statusCode, headers, body } }to stop the request and send an immediate response to the client. The upstream service is not called.headersis an array of[name, value]pairs, andbodyis optional and can be aUint8Arrayor a string.
If requestFilter returns an unexpected value, the gateway logs a warning and treats it as continue.
Logging
Calls to the console methods are written to the gateway logs at the corresponding level:
| Console method | Gateway log level |
|---|---|
|
debug |
|
info |
|
warn |
|
error |
Examples
Add and Remove Headers
This example adds a header to the request and the response, and removes a header from each:
- policyRef:
name: javascript-scripting-flex
config:
script: |
export function requestFilter(request) {
request.setHeader("x-processed-by", "javascript-policy");
request.removeHeader("x-internal");
}
export function responseFilter(response) {
response.setHeader("x-served-by", "omni-gateway");
response.removeHeader("server");
}
Block a Request with an Early Response
This example rejects a request that is missing an API key and returns a 401 response without calling the upstream service:
- policyRef:
name: javascript-scripting-flex
config:
script: |
export function requestFilter(request) {
if (!request.getHeader("x-api-key")) {
return {
flow: "break",
response: {
statusCode: 401,
headers: [["content-type", "text/plain"]],
body: "Missing API key",
},
};
}
}
Pass Data from the Request to the Response
This example reads a value during the request phase and uses it during the response phase:
- policyRef:
name: javascript-scripting-flex
config:
script: |
export function requestFilter(request) {
const id = request.getHeader("x-request-id") || "unknown";
return { flow: "continue", data: { id } };
}
export function responseFilter(response, requestData) {
if (requestData.flow === "continue" && requestData.data) {
response.setHeader("x-request-id", requestData.data.id);
}
}
Transform the Response Body
This example replaces the response body with a new string:
- policyRef:
name: javascript-scripting-flex
config:
script: |
export function responseFilter(response) {
if (response.containsBody()) {
response.setBodyString('{"message":"transformed by gateway"}');
response.setHeader("content-type", "application/json");
}
}