You can use the groovy
policy to execute Groovy scripts at any stage of request processing within the Gateway.
This policy is applicable to the following API types:
- v2 APIs
- v4 HTTP proxy APIs
- v4 message APIs
Note: The Groovy policy is not supported by v4 TCP or Native APIs.
Several variables are automatically bound to the Groovy script. These let you read, and potentially modify, their values to define the behavior of the policy.
Variable | Description |
---|---|
request |
Inbound HTTP request |
response |
Outbound HTTP response |
message |
Message transiting the Gateway |
context |
Context usable to access external components such as services and resources |
result |
Object to return to alter the outcome of the request/response |
See the Usage section for object attributes and methods.
Variable | Description |
---|---|
request.content |
When "Read content" is enabled |
response.content |
When "Read content" is enabled |
message.content |
Always available |
To change the outcome of the request or response to access the result
object, use the following properties in your script:
Attribute | Type | Description |
---|---|---|
state |
PolicyResult.State | To indicate a failure |
code |
integer | An HTTP status code |
error |
string | The error message |
key |
string | The key of a response template |
Here is an example on the request phase:
import io.gravitee.policy.groovy.PolicyResult.State
if (request.headers.containsKey('X-Gravitee-Break')) {
result.key = 'RESPONSE_TEMPLATE_KEY'
result.state = State.FAILURE
result.code = 500
result.error = 'Stop request processing due to X-Gravitee-Break header'
} else {
request.headers.'X-Groovy-Policy' = 'ok'
}
To override content in a proxy API, you must enable "Override content." "Override content" is always enabled for message APIs.
To override existing content, make your script the expected content.
Input body content
{
"age": 32,
"firstname": "John",
"lastname": "Doe"
}
Groovy script
You must enable "Read content" for this to work
import groovy.json.JsonSlurper
import groovy.json.JsonOutput
def jsonSlurper = new JsonSlurper()
def content = jsonSlurper.parseText(response.content)
content.firstname = 'Hacked ' + content.firstname
content.country = 'US'
return JsonOutput.toJson(content)
Output body content
{
"age": 32,
"firstname": "Hacked John",
"lastname": "Doe",
"country": "US"
}
request.<property>
Property | Type | Mutable | Description |
---|---|---|---|
content |
String |
Body of the request. | |
transactionId |
String |
Unique identifier for the transaction. | |
clientIdentifier |
String |
Identifies the client that made the request. | |
uri |
String |
The complete request URI. | |
host |
String |
Host from the incoming request. | |
originalHost |
String |
Host as originally received before any internal rewriting. | |
contextPath |
String |
API context path. | |
pathInfo |
String |
Path beyond the context path. | |
path |
String |
The full path component of the request URI. | |
parameters |
Map<String, <List<String>> |
✅️ | Query parameters as a multi-value map. For methods, refer to Multimap methods. |
pathParameters |
Map<String, <List<String>> |
Parameters extracted from path templates. For methods, refer to Multimap methods. Note that altering method are useless in this context. | |
headers |
Map<String, String> |
âś… | HTTP headers. For methods, refer to Headers methods. |
method |
HttpMethod (enum) |
HTTP method used in the request (e.g., GET, POST). | |
scheme |
String |
The scheme (HTTP or HTTPS) used by the request. | |
version |
HttpVersion (enum) |
HTTP protocol version: HTTP_1_0 , HTTP_1_1 , HTTP_2 . |
|
timestamp |
long |
Epoch timestamp of when the request was received. | |
remoteAddress |
String |
IP address of the client. | |
localAddress |
String |
Local IP address of the server handling the request. |
response.<property>
Property | Type | Mutable | Description |
---|---|---|---|
content |
String |
Body of the response. | |
status |
int |
Response status code. | |
reason |
String |
Reason for the status. | |
headers |
Map<String, String> |
âś… | HTTP headers wrapped in a bindable object. For methods, refer to Headers methods. |
message.<property>
Property | Type | Mutable | Description |
---|---|---|---|
correlationId |
String | Correlation ID to track the message. | |
parentCorrelationId |
String | Parent correlation ID. | |
timestamp |
long | Epoch (ms) timestamp. | |
error |
boolean | Message is an error message. | |
metadata |
Map<String, Object> | âś… | Message metadata. Dependent on the messaging system. |
headers |
Map<String, String> | âś… | Message headers. For methods, refer to Headers methods. |
content |
String | Message body as a string. | |
contentAsBase64 |
String | Message body bytes as a basic base64 string. | |
contentAsByteArray |
byte[] | Message body bytes. | |
attributes |
Map<String, Object> | âś… | Message attributes wrapped in a bindable object. For methods, see below. |
Message attributes methods
message.attributes.<method>
Method | Arguments (type) | Return type | Description |
---|---|---|---|
remove |
key (Object ) |
Remove an attribute. | |
containsKey |
key (Object ) |
boolean |
Check if an attribute exists. |
containsValue |
key (Object ) |
boolean |
Check if one of the attributes contains the value. |
empty |
boolean |
true when the attribute exists. |
|
size |
int |
Return an attribute count. | |
keySet |
Set<String> |
All attribute names. |
Property | Type | Mutable | Description |
---|---|---|---|
attributes |
Map<String, Object> | âś… | Context attributes as a map. |
attributeNames |
Set | All attribute names. | |
attributeAsList |
List | All attribute values. |
Context attributes methods
context.attributes.<method>
Use a prefix to get an attribute or verify that it exists.
For example, context.attributes.'my-specific-attribute'
returns an attribute map entry with the key gravitee.attribute.my-specific-attribute
.
Refer to the Gravitee documentation for available attributes.
Note: This rule only applies when reading an attribute. You must explicitly add gravitee.attribute.<key>
to alter an attribute.
Method | Arguments (type) | Return type | Description |
---|---|---|---|
get |
key (Object ) |
Object |
Get a Gravitee attribute starting with gravitee.attribute. . Works with Groovy context.attributes.'key' syntax using the same prefix rule. |
containsKey |
key (Object ) |
boolean |
Check if a Gravitee attribute starting with gravitee.attribute. exists. |
put |
key (String ) value (Object ) |
Equivalent of context.attributes.'key' = value . |
Other methods of java.util.Map
are accessible, such as remove
and size
.
Applicable to request.headers
, response.headers
, message.headers
.
Method | Arguments (type) | Return type | Description |
---|---|---|---|
remove |
key (Object ) |
Remove a header. | |
containsKey |
key (Object ) |
boolean |
Check if a header exists. |
clear |
Remove all headers. | ||
empty |
boolean |
true when header exists. |
|
size |
int |
Return header count. | |
keySet |
Set<String> |
All header names. |
Multimap lets you use several values for a single map entry without pre-initializing a collection.
Multimap is applicable to request.parameters
and request.pathParameters
.
All methods of the Gravitee MultiValueMap implementation: getFirst
, add
, set
, setAll
, toSingleValueMap
, containsAllKeys
.
All java.util.Map
are also available.
These templates are defined at the API level, in the "Entrypoint" section for v4 APIs, or in "Response Templates" for v2 APIs. The error keys sent by this policy are as follows:
Key |
---|
GROOVY_EXECUTION_FAILURE |
The groovy
policy can be applied to the following API types and flow phases.
PROXY
MESSAGE
- Request
- Response
- Publish
- Subscribe
Strikethrough text indicates that a version is deprecated.
Plugin version | APIM |
---|---|
4.x | 4.9.x and above |
3.x | 4.6.x to 4.8.x |
2.x | 4.5.x and below |
The groovy
policy includes a native sandbox feature, which lets you safely run Groovy scripts. The sandbox is based on a predefined list of allowed methods, fields, constructors, and annotations.
The complete whitelist can be found here: gravitee groovy whitelist.
This whitelist should address the majority of possible use cases. If you have specific needs which are not satisfied by the built-in whitelist, you can extend, or even replace, the list with your own declarations. To modify the whitelist, configure the gravitee.yml
file to specify:
groovy.whitelist.mode
:append
orreplace
. This lets you append whitelisted definitions to the built-in list, or completely replace it. We recommend selectingappend
to avoid unintended behaviors.groovy.whitelist.list
: This lets you declare other methods, constructors, fields, or annotations in the whitelist.- Start with
method
to allow a specific method (complete signature) - Start with
class
to allow a complete class. All methods, constructors, and fields of the class are then accessible. - Start with
new
to allow a specific constructor (complete signature) - Start with
field
to allow access to a specific field of a class - Start with
annotation
to allow use of a specific annotation
- Start with
gravitee.yml
groovy:
whitelist:
mode: append
list:
- method com.acme.common.Strings toTitleCase java.lang.String
- class com.acme.common.Strings
Environment variables (Helm)
gateway:
env:
- name: GRAVITEE_GROOVY_WHITELIST_MODE
value: append
- name: GRAVITEE_GROOVY_WHITELIST_LIST_0
value: "method com.acme.common.Strings toTitleCase java.lang.String"
- name: GRAVITEE_GROOVY_WHITELIST_LIST_1
value: "class com.acme.common.Strings"
Security implications
Exercise care when using classes or methods. In some cases, giving access to all methods of a class may make unwanted methods accessible via transitivity and risk security breaches.
Name json name |
Type constraint |
Mandatory | Default | Description |
---|---|---|---|---|
Override contentoverrideContent |
boolean | Enable to override the content of the request or response with the value returned by your script. | ||
Read contentreadContent |
boolean | Enable if your script needs to access the content of the HTTP request or response in your script. | ||
Scriptscript |
string | Groovy script to evaluate. |
Proxy API on Request phase
{
"api": {
"definitionVersion": "V4",
"type": "PROXY",
"name": "Groovy example API",
"flows": [
{
"name": "Common Flow",
"enabled": true,
"selectors": [
{
"type": "HTTP",
"path": "/",
"pathOperator": "STARTS_WITH"
}
],
"request": [
{
"name": "Groovy",
"enabled": true,
"policy": "groovy",
"configuration":
{
"readContent": false,
"overrideContent": false,
"script": "response.headers.remove 'X-Powered-By'\nresponse.headers.'X-Gravitee-Gateway-Version' = '0.14.0'"
}
}
]
}
]
}
}
Message API CRD
apiVersion: "gravitee.io/v1alpha1"
kind: "ApiV4Definition"
metadata:
name: "groovy-message-api-crd"
spec:
name: "Groovy example"
type: "MESSAGE"
flows:
- name: "Common Flow"
enabled: true
selectors:
matchRequired: false
mode: "DEFAULT"
request:
- name: "Groovy"
enabled: true
policy: "groovy"
configuration:
overrideContent: false
readContent: false
script: |-
response.headers.remove 'X-Powered-By'
response.headers.'X-Gravitee-Gateway-Version' = '0.14.0'
4.0.0 (2025-09-18)
- include cause throwable in the execution failure (1cf1409)
- requires APIM version 4.9.0 or later
3.0.3 (2025-08-08)
- deps: update dependency org.apache.commons:commons-lang3 to v3.18.0 [security] (7913dc6)
3.0.2 (2025-06-18)
- doc gen (24bde45)
3.0.1 (2025-01-15)
- deps: upgrade groovy-sandbox to 1.30 (32fba8f)
3.0.0 (2024-12-30)
- deps: bump apim version (4eb775a)
- use latest node and apim version (fb3706b)
- warning messages (5b3b334)
- support new OpenTelemetry feature (14ca260)
- Tracer interface is not more available through tracer-api module
- tracer and components are no longer allowed for groovy context
3.0.0-alpha.3 (2024-12-30)
- deps: bump apim version (4eb775a)
3.0.0-alpha.2 (2024-12-16)
- warning messages (5b3b334)
3.0.0-alpha.1 (2024-11-06)
- use latest node and apim version (fb3706b)
- support new OpenTelemetry feature (14ca260)
- Tracer interface is not more available through tracer-api module
- tracer and components are no longer allowed for groovy context
2.6.3 (2024-12-13)
- warning messages in logs for groovy classes (612f554)
2.6.2 (2024-10-02)
- avoid blocking eventloop when compiling (5bccbe2)
2.6.1 (2024-08-21)
2.6.0 (2024-06-03)
- add methods for binary content of messages (707519e)
2.5.2 (2023-11-09)
- do not write body if onRequest/Response only (62f692c)
2.5.1 (2023-10-05)
- add request and response to message phases (154db98)
2.5.0 (2023-10-02)
- add message level support to policy (632813e)
2.4.2 (2023-07-20)
- update policy description (b0e00a0)
2.4.1 (2023-06-27)
- add policy result key to readme (f8b6774)
2.4.0 (2023-06-27)
- allow to add response template key in policy result (b26046e)
2.3.0 (2023-04-12)
- properly return the scheme with
scheme()
andgetScheme()
methods (2a827b9)
- add a
getHost()
method so that "request.host" expression is correctly resolved (12a3a04)
2.2.2 (2022-06-24)
- whitelist gateway-api HttpHeaders (f4bd528)
2.2.1 (2022-06-15)
- make header accessor return an iterable instead of a string (46774f2)
2.2.0 (2022-03-17)
- resolve GStringImpl.trim() (4ff3390)
- resolve iteration on map (d8fd8e5), closes gravitee-io/issues#7302
- add EncodingGroovyMethods to whitelist (2ba4f27)
2.1.0 (2022-01-24)
- headers: Internal rework and introduce HTTP Headers API (3a3aa33), closes gravitee-io/issues#6772
- perf: adapt policy for new classloader system (08c3aea), closes gravitee-io/issues#6758