diff --git a/api/v1alpha1/ext_proc_types.go b/api/v1alpha1/ext_proc_types.go
index 7499b9f8e4f..ef5e409d9db 100644
--- a/api/v1alpha1/ext_proc_types.go
+++ b/api/v1alpha1/ext_proc_types.go
@@ -9,6 +9,42 @@ import (
gwapiv1 "sigs.k8s.io/gateway-api/apis/v1"
)
+// +kubebuilder:validation:Enum=Streamed;Buffered;BufferedPartial
+type ExtProcBodyProcessingMode string
+
+const (
+ // StreamedExtProcBodyProcessingMode will stream the body to the server in pieces as they arrive at the proxy.
+ StreamedExtProcBodyProcessingMode ExtProcBodyProcessingMode = "Streamed"
+ // BufferedExtProcBodyProcessingMode will buffer the message body in memory and send the entire body at once. If the body exceeds the configured buffer limit, then the downstream system will receive an error.
+ BufferedExtProcBodyProcessingMode ExtProcBodyProcessingMode = "Buffered"
+ // BufferedPartialExtBodyHeaderProcessingMode will buffer the message body in memory and send the entire body in one chunk. If the body exceeds the configured buffer limit, then the body contents up to the buffer limit will be sent.
+ BufferedPartialExtBodyHeaderProcessingMode ExtProcBodyProcessingMode = "BufferedPartial"
+)
+
+// ProcessingModeOptions defines if headers or body should be processed by the external service
+type ProcessingModeOptions struct {
+ // Defines body processing mode
+ //
+ // +optional
+ Body *ExtProcBodyProcessingMode `json:"body,omitempty"`
+}
+
+// ExtProcProcessingMode defines if and how headers and bodies are sent to the service.
+// https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/http/ext_proc/v3/processing_mode.proto#envoy-v3-api-msg-extensions-filters-http-ext-proc-v3-processingmode
+type ExtProcProcessingMode struct {
+ // Defines processing mode for requests. If present, request headers are sent. Request body is processed according
+ // to the specified mode.
+ //
+ // +optional
+ Request *ProcessingModeOptions `json:"request,omitempty"`
+
+ // Defines processing mode for responses. If present, response headers are sent. Response body is processed according
+ // to the specified mode.
+ //
+ // +optional
+ Response *ProcessingModeOptions `json:"response,omitempty"`
+}
+
// +kubebuilder:validation:XValidation:rule="has(self.backendRef) ? (!has(self.backendRef.group) || self.backendRef.group == \"\") : true", message="group is invalid, only the core API group (specified by omitting the group field or setting it to an empty string) is supported"
// +kubebuilder:validation:XValidation:rule="has(self.backendRef) ? (!has(self.backendRef.kind) || self.backendRef.kind == 'Service') : true", message="kind is invalid, only Service (specified by omitting the kind field or setting it to 'Service') is supported"
//
@@ -34,6 +70,12 @@ type ExtProc struct {
//
// +optional
FailOpen *bool `json:"failOpen,omitempty"`
+
+ // ProcessingMode defines how request and response body is processed
+ // Default: header and body are not sent to the external processor
+ //
+ // +optional
+ ProcessingMode *ExtProcProcessingMode `json:"processingMode,omitempty"`
}
// ExtProcService defines the gRPC External Processing service using the envoy grpc client
diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go
index a1a7ca77f73..d1f40b777de 100644
--- a/api/v1alpha1/zz_generated.deepcopy.go
+++ b/api/v1alpha1/zz_generated.deepcopy.go
@@ -1597,6 +1597,11 @@ func (in *ExtProc) DeepCopyInto(out *ExtProc) {
*out = new(bool)
**out = **in
}
+ if in.ProcessingMode != nil {
+ in, out := &in.ProcessingMode, &out.ProcessingMode
+ *out = new(ExtProcProcessingMode)
+ (*in).DeepCopyInto(*out)
+ }
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExtProc.
@@ -1625,6 +1630,31 @@ func (in *ExtProcBackendRef) DeepCopy() *ExtProcBackendRef {
return out
}
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ExtProcProcessingMode) DeepCopyInto(out *ExtProcProcessingMode) {
+ *out = *in
+ if in.Request != nil {
+ in, out := &in.Request, &out.Request
+ *out = new(ProcessingModeOptions)
+ (*in).DeepCopyInto(*out)
+ }
+ if in.Response != nil {
+ in, out := &in.Response, &out.Response
+ *out = new(ProcessingModeOptions)
+ (*in).DeepCopyInto(*out)
+ }
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExtProcProcessingMode.
+func (in *ExtProcProcessingMode) DeepCopy() *ExtProcProcessingMode {
+ if in == nil {
+ return nil
+ }
+ out := new(ExtProcProcessingMode)
+ in.DeepCopyInto(out)
+ return out
+}
+
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ExtensionAPISettings) DeepCopyInto(out *ExtensionAPISettings) {
*out = *in
@@ -2947,6 +2977,26 @@ func (in *PerRetryPolicy) DeepCopy() *PerRetryPolicy {
return out
}
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ProcessingModeOptions) DeepCopyInto(out *ProcessingModeOptions) {
+ *out = *in
+ if in.Body != nil {
+ in, out := &in.Body, &out.Body
+ *out = new(ExtProcBodyProcessingMode)
+ **out = **in
+ }
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProcessingModeOptions.
+func (in *ProcessingModeOptions) DeepCopy() *ProcessingModeOptions {
+ if in == nil {
+ return nil
+ }
+ out := new(ProcessingModeOptions)
+ in.DeepCopyInto(out)
+ return out
+}
+
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ProxyAccessLog) DeepCopyInto(out *ProxyAccessLog) {
*out = *in
diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml
index 4861dd1fcc0..f73b96b26ce 100644
--- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml
+++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_envoyextensionpolicies.yaml
@@ -227,6 +227,38 @@ spec:
Default: 200ms
pattern: ^([0-9]{1,5}(h|m|s|ms)){1,4}$
type: string
+ processingMode:
+ description: |-
+ ProcessingMode defines how request and response body is processed
+ Default: header and body are not sent to the external processor
+ properties:
+ request:
+ description: |-
+ Defines processing mode for requests. If present, request headers are sent. Request body is processed according
+ to the specified mode.
+ properties:
+ body:
+ description: Defines body processing mode
+ enum:
+ - Streamed
+ - Buffered
+ - BufferedPartial
+ type: string
+ type: object
+ response:
+ description: |-
+ Defines processing mode for responses. If present, response headers are sent. Response body is processed according
+ to the specified mode.
+ properties:
+ body:
+ description: Defines body processing mode
+ enum:
+ - Streamed
+ - Buffered
+ - BufferedPartial
+ type: string
+ type: object
+ type: object
required:
- backendRef
type: object
diff --git a/site/content/en/latest/api/extension_types.md b/site/content/en/latest/api/extension_types.md
index 526e8012502..82d7de15e7f 100644
--- a/site/content/en/latest/api/extension_types.md
+++ b/site/content/en/latest/api/extension_types.md
@@ -1166,6 +1166,7 @@ _Appears in:_
| `backendRefs` | _[BackendRef](#backendref) array_ | false | BackendRefs defines the configuration of the external processing service |
| `messageTimeout` | _[Duration](#duration)_ | false | MessageTimeout is the timeout for a response to be returned from the external processor
Default: 200ms |
| `failOpen` | _boolean_ | false | FailOpen defines if requests or responses that cannot be processed due to connectivity to the
external processor are terminated or passed-through.
Default: false |
+| `processingMode` | _[ExtProcProcessingMode](#extprocprocessingmode)_ | false | ProcessingMode defines how request and response body is processed
Default: header and body are not sent to the external processor |
#### ExtProcBackendRef
@@ -1188,6 +1189,38 @@ _Appears in:_
| `port` | _[PortNumber](#portnumber)_ | false | Port specifies the destination port number to use for this resource.
Port is required when the referent is a Kubernetes Service. In this
case, the port number is the service port number, not the target port.
For other resources, destination port might be derived from the referent
resource or this field. |
+#### ExtProcBodyProcessingMode
+
+_Underlying type:_ _string_
+
+
+
+_Appears in:_
+- [ProcessingModeOptions](#processingmodeoptions)
+
+| Value | Description |
+| ----- | ----------- |
+| `Streamed` | StreamedExtProcBodyProcessingMode will stream the body to the server in pieces as they arrive at the proxy.
|
+| `Buffered` | BufferedExtProcBodyProcessingMode will buffer the message body in memory and send the entire body at once. If the body exceeds the configured buffer limit, then the downstream system will receive an error.
|
+| `BufferedPartial` | BufferedPartialExtBodyHeaderProcessingMode will buffer the message body in memory and send the entire body in one chunk. If the body exceeds the configured buffer limit, then the body contents up to the buffer limit will be sent.
|
+
+
+#### ExtProcProcessingMode
+
+
+
+ExtProcProcessingMode defines if and how headers and bodies are sent to the service.
+https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/http/ext_proc/v3/processing_mode.proto#envoy-v3-api-msg-extensions-filters-http-ext-proc-v3-processingmode
+
+_Appears in:_
+- [ExtProc](#extproc)
+
+| Field | Type | Required | Description |
+| --- | --- | --- | --- |
+| `request` | _[ProcessingModeOptions](#processingmodeoptions)_ | false | Defines processing mode for requests. If present, request headers are sent. Request body is processed according
to the specified mode. |
+| `response` | _[ProcessingModeOptions](#processingmodeoptions)_ | false | Defines processing mode for responses. If present, response headers are sent. Response body is processed according
to the specified mode. |
+
+
#### ExtensionAPISettings
@@ -2136,6 +2169,20 @@ _Appears in:_
| `backOff` | _[BackOffPolicy](#backoffpolicy)_ | false | Backoff is the backoff policy to be applied per retry attempt. gateway uses a fully jittered exponential
back-off algorithm for retries. For additional details,
see https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/router_filter#config-http-filters-router-x-envoy-max-retries |
+#### ProcessingModeOptions
+
+
+
+ProcessingModeOptions defines if headers or body should be processed by the external service
+
+_Appears in:_
+- [ExtProcProcessingMode](#extprocprocessingmode)
+
+| Field | Type | Required | Description |
+| --- | --- | --- | --- |
+| `body` | _[ExtProcBodyProcessingMode](#extprocbodyprocessingmode)_ | false | Defines body processing mode |
+
+
#### ProviderType
_Underlying type:_ _string_
diff --git a/test/cel-validation/envoyextensionpolicy_test.go b/test/cel-validation/envoyextensionpolicy_test.go
index 2283212cd5c..67200306a34 100644
--- a/test/cel-validation/envoyextensionpolicy_test.go
+++ b/test/cel-validation/envoyextensionpolicy_test.go
@@ -233,6 +233,42 @@ func TestEnvoyExtensionPolicyTarget(t *testing.T) {
},
wantErrors: []string{"spec.extProc[0]: Invalid value: \"object\": kind is invalid, only Service (specified by omitting the kind field or setting it to 'Service') is supported"},
},
+ {
+ desc: "ExtProc with invalid fields",
+ mutate: func(sp *egv1a1.EnvoyExtensionPolicy) {
+ sp.Spec = egv1a1.EnvoyExtensionPolicySpec{
+ ExtProc: []egv1a1.ExtProc{
+ {
+ BackendRef: egv1a1.ExtProcBackendRef{
+ BackendObjectReference: gwapiv1.BackendObjectReference{
+ Name: "grpc-proc-service",
+ Port: ptr.To(gwapiv1.PortNumber(80)),
+ },
+ },
+ ProcessingMode: &egv1a1.ExtProcProcessingMode{
+ Request: &egv1a1.ProcessingModeOptions{
+ Body: ptr.To(egv1a1.ExtProcBodyProcessingMode("not-a-body-mode")),
+ },
+ Response: &egv1a1.ProcessingModeOptions{
+ Body: ptr.To(egv1a1.ExtProcBodyProcessingMode("not-a-body-mode")),
+ },
+ },
+ },
+ },
+ TargetRef: gwapiv1a2.PolicyTargetReferenceWithSectionName{
+ PolicyTargetReference: gwapiv1a2.PolicyTargetReference{
+ Group: "gateway.networking.k8s.io",
+ Kind: "Gateway",
+ Name: "eg",
+ },
+ },
+ }
+ },
+ wantErrors: []string{
+ "spec.extProc[0].processingMode.response.body: Unsupported value: \"not-a-body-mode\": supported values: \"Streamed\", \"Buffered\", \"BufferedPartial\"",
+ "spec.extProc[0].processingMode.request.body: Unsupported value: \"not-a-body-mode\": supported values: \"Streamed\", \"Buffered\", \"BufferedPartial\"",
+ },
+ },
}
for _, tc := range cases {