From 9cd388d72d9be853e0ff2dccf6097edb90f82257 Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Thu, 13 Mar 2025 21:38:36 +0000 Subject: [PATCH 01/26] xDS: ext_proc: add GRPC processing mode, and clean up docs Signed-off-by: Mark D. Roth --- .../filters/http/ext_proc/v3/ext_proc.proto | 74 ++++++++++--------- .../http/ext_proc/v3/processing_mode.proto | 28 ++++--- .../ext_proc/v3/external_processor.proto | 68 +++++++++-------- 3 files changed, 95 insertions(+), 75 deletions(-) diff --git a/api/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto b/api/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto index 7e4fbffb658bd..111a8d2ae6baf 100644 --- a/api/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto +++ b/api/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto @@ -47,8 +47,6 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE; // // * Whether it receives the response message at all // * Whether it receives the message body at all, in separate chunks, or as a single buffer -// * Whether subsequent HTTP requests are transmitted synchronously or whether they are -// sent asynchronously. // * To modify request or response trailers if they already exist // // The filter supports up to six different processing steps. Each is represented by @@ -56,9 +54,16 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE; // processor must send a matching response. // // * Request headers: Contains the headers from the original HTTP request. -// * Request body: Delivered if they are present and sent in a single message if -// the BUFFERED or BUFFERED_PARTIAL mode is chosen, in multiple messages if the -// STREAMED mode is chosen, and not at all otherwise. +// * Request body: If the body is present, the behavior depends on the +// body send mode: +// * BUFFERED or BUFFERED_PARTIAL: Entire body is sent to the external +// processor in a single message. +// * STREAMED or FULL_DUPLEX_STREAMED: Body will be split across +// multiple messages sent to the external processor. +// * GRPC: As each gRPC message arrives, it will be sent to the external +// processor. There will be exactly one gRPC message in each message +// sent to the external processor. +// * NONE: Body will not be sent to the external processor. // * Request trailers: Delivered if they are present and if the trailer mode is set // to SEND. // * Response headers: Contains the headers from the HTTP response. Keep in mind @@ -74,7 +79,7 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE; // from the external processor. The latter is only enabled if allow_mode_override is // set to true. This way, a processor may, for example, use information // in the request header to determine whether the message body must be examined, or whether -// the proxy should simply stream it straight through. +// the data plane should simply stream it straight through. // // All of this together allows a server to process the filter traffic in fairly // sophisticated ways. For example: @@ -83,12 +88,8 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE; // on the content of the headers. // * A server may choose to immediately reject some messages based on their HTTP // headers (or other dynamic metadata) and more carefully examine others. -// * A server may asynchronously monitor traffic coming through the filter by inspecting -// headers, bodies, or both, and then decide to switch to a synchronous processing -// mode, either permanently or temporarily. // -// The protocol itself is based on a bidirectional gRPC stream. Envoy will send the -// server +// The protocol itself is based on a bidirectional gRPC stream. The data plane will send the server // :ref:`ProcessingRequest ` // messages, and the server must reply with // :ref:`ProcessingResponse `. @@ -123,7 +124,6 @@ message ExternalProcessor { reserved "async_mode"; // Configuration for the gRPC service that the filter will communicate with. - // The filter supports both the "Envoy" and "Google" gRPC clients. // Only one of ``grpc_service`` or ``http_service`` can be set. // It is required that one of them must be set. config.core.v3.GrpcService grpc_service = 1 @@ -139,14 +139,14 @@ message ExternalProcessor { // can not be configured to send any body or trailers. i.e, http_service only supports // sending request or response headers to the side stream server. // - // With this configuration, Envoy behavior: + // With this configuration, the data plane behavior is: // // 1. The headers are first put in a proto message // :ref:`ProcessingRequest `. // // 2. This proto message is then transcoded into a JSON text. // - // 3. Envoy then sends a HTTP POST message with content-type as "application/json", + // 3. The data plane then sends a HTTP POST message with content-type as "application/json", // and this JSON text as body to the side stream server. // // After the side-stream receives this HTTP request message, it is expected to do as follows: @@ -159,7 +159,7 @@ message ExternalProcessor { // // 3. It converts ``ProcessingResponse`` proto message into a JSON text. // - // 4. It then sends a HTTP response back to Envoy with status code as "200", + // 4. It then sends a HTTP response back to the data plane with status code as "200", // content-type as "application/json" and sets the JSON text as the body. // ExtProcHttpService http_service = 20 [ @@ -180,28 +180,30 @@ message ExternalProcessor { // sent. See ProcessingMode for details. ProcessingMode processing_mode = 3; - // Envoy provides a number of :ref:`attributes ` + // The data plane provides a number of :ref:`attributes ` // for expressive policies. Each attribute name provided in this field will be - // matched against that list and populated in the request_headers message. + // matched against that list and populated in the + // :ref:`ProcessingRequest.attributes ` field. // See the :ref:`attribute documentation ` // for the list of supported attributes and their types. repeated string request_attributes = 5; - // Envoy provides a number of :ref:`attributes ` + // The data plane provides a number of :ref:`attributes ` // for expressive policies. Each attribute name provided in this field will be - // matched against that list and populated in the response_headers message. + // matched against that list and populated in the + // :ref:`ProcessingRequest.attributes ` field. // See the :ref:`attribute documentation ` // for the list of supported attributes and their types. repeated string response_attributes = 6; - // Specifies the timeout for each individual message sent on the stream and - // when the filter is running in synchronous mode. Whenever the proxy sends - // a message on the stream that requires a response, it will reset this timer, - // and will stop processing and return an error (subject to the processing mode) - // if the timer expires before a matching response is received. There is no - // timeout when the filter is running in asynchronous mode. Zero is a valid - // config which means the timer will be triggered immediately. If not - // configured, default is 200 milliseconds. + // Specifies the timeout for each individual message sent on the stream. + // Whenever the data plane sends a message on the stream that requires a + // response, it will reset this timer, and will stop processing and return + // an error (subject to the processing mode) if the timer expires before a + // matching response is received. There is no timeout when the filter is + // running in observability mode. Zero is a valid config which means the + // timer will be triggered immediately. If not configured, default is 200 + // milliseconds. google.protobuf.Duration message_timeout = 7 [(validate.rules).duration = { lte {seconds: 3600} gte {} @@ -218,7 +220,7 @@ message ExternalProcessor { // :ref:`header_prefix ` // (which is usually "x-envoy"). // Note that changing headers such as "host" or ":authority" may not in itself - // change Envoy's routing decision, as routes can be cached. To also force the + // change the data plane's routing decision, as routes can be cached. To also force the // route to be recomputed, set the // :ref:`clear_route_cache ` // field to true in the same response. @@ -260,9 +262,9 @@ message ExternalProcessor { // If true, send each part of the HTTP request or response specified by ProcessingMode // without pausing on filter chain iteration. It is "Send and Go" mode that can be used - // by external processor to observe Envoy data and status. In this mode: + // by external processor to observe the request's data and status. In this mode: // - // 1. Only STREAMED body processing mode is supported and any other body processing modes will be + // 1. Only STREAMED and GRPC body processing modes are supported and any other body processing modes will be // ignored. NONE mode(i.e., skip body processing) will still work as expected. // // 2. External processor should not send back processing response, as any responses will be ignored. @@ -300,12 +302,12 @@ message ExternalProcessor { // Specifies the deferred closure timeout for gRPC stream that connects to external processor. Currently, the deferred stream closure // is only used in :ref:`observability_mode `. // In observability mode, gRPC streams may be held open to the external processor longer than the lifetime of the regular client to - // backend stream lifetime. In this case, Envoy will eventually timeout the external processor stream according to this time limit. + // backend stream lifetime. In this case, the data plane will eventually timeout the external processor stream according to this time limit. // The default value is 5000 milliseconds (5 seconds) if not specified. google.protobuf.Duration deferred_close_timeout = 19; // Send body to the side stream server once it arrives without waiting for the header response from that server. - // It only works for STREAMED body processing mode. For any other body processing modes, it is ignored. + // It only works for STREAMED and GRPC body processing modes. For any other body processing modes, it is ignored. // The server has two options upon receiving a header request: // // 1. Instant Response: send the header response as soon as the header request is received. @@ -314,9 +316,9 @@ message ExternalProcessor { // // In all scenarios, the header-body ordering must always be maintained. // - // If enabled Envoy will ignore the + // If enabled the data plane will ignore the // :ref:`mode_override ` - // value that the server sends in the header response. This is because Envoy may have already + // value that the server sends in the header response. This is because the data plane may have already // sent the body to the server, prior to processing the header response. bool send_body_without_waiting_for_header_response = 21; @@ -415,7 +417,9 @@ message ExtProcOverrides { // [#not-implemented-hide:] // Set a different asynchronous processing option than the default. - bool async_mode = 2; + // Deprecated and not implemented. + bool async_mode = 2 + [deprecated = true, (envoy.annotations.deprecated_at_minor_version) = "3.0"]; // [#not-implemented-hide:] // Set different optional attributes than the default setting of the diff --git a/api/envoy/extensions/filters/http/ext_proc/v3/processing_mode.proto b/api/envoy/extensions/filters/http/ext_proc/v3/processing_mode.proto index 467320d4a417b..482542f1f31e6 100644 --- a/api/envoy/extensions/filters/http/ext_proc/v3/processing_mode.proto +++ b/api/envoy/extensions/filters/http/ext_proc/v3/processing_mode.proto @@ -65,8 +65,7 @@ message ProcessingMode { // Do not send the body at all. This is the default. NONE = 0; - // Stream the body to the server in pieces as they arrive at the - // proxy. + // Stream the body to the server in pieces as they are seen. STREAMED = 1; // Buffer the message body in memory and send the entire body at once. @@ -79,11 +78,11 @@ message ProcessingMode { // up to the buffer limit will be sent. BUFFERED_PARTIAL = 3; - // Envoy streams the body to the server in pieces as they arrive. + // The ext_proc client streams the body to the server in pieces as they arrive. // // 1) The server may choose to buffer any number chunks of data before processing them. // After it finishes buffering, the server processes the buffered data. Then it splits the processed - // data into any number of chunks, and streams them back to Envoy one by one. + // data into any number of chunks, and streams them back to the client one by one. // The server may continuously do so until the complete body is processed. // The individual response chunk size is recommended to be no greater than 64K bytes, or // :ref:`max_receive_message_length ` @@ -98,17 +97,28 @@ message ProcessingMode { // // In this body mode: // * The corresponding trailer mode has to be set to ``SEND``. - // * Envoy will send body and trailers (if present) to the server as they arrive. + // * The client will send body and trailers (if present) to the server as they arrive. // Sending the trailers (if present) is to inform the server the complete body arrives. - // In case there are no trailers, then Envoy will set + // In case there are no trailers, then the client will set // :ref:`end_of_stream ` // to true as part of the last body chunk request to notify the server that no other data is to be sent. // * The server needs to send // :ref:`StreamedBodyResponse ` - // to Envoy in the body response. - // * Envoy will stream the body chunks in the responses from the server to the upstream/downstream as they arrive. - + // to the client in the body response. + // * The client will stream the body chunks in the responses from the server to the upstream/downstream as they arrive. FULL_DUPLEX_STREAMED = 4; + + // [#not-implemented-hide:] + // gRPC traffic. In this mode, the ext_proc client will deframe the + // individual gRPC messages inside the HTTP/2 DATA frames, and as each + // message is deframed, it will be sent to the ext_proc server as a + // :ref:`request_body + // ` + // or :ref:`response_body + // `. + // If the ext_proc server modifies the body, that modified body will + // be used to replace the gRPC message in the stream. + GRPC = 5; } // How to handle the request header. Default is "SEND". diff --git a/api/envoy/service/ext_proc/v3/external_processor.proto b/api/envoy/service/ext_proc/v3/external_processor.proto index dcf37993dd381..57d16b8437c66 100644 --- a/api/envoy/service/ext_proc/v3/external_processor.proto +++ b/api/envoy/service/ext_proc/v3/external_processor.proto @@ -27,28 +27,29 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE; // as part of a filter chain. // The overall external processing protocol works like this: // -// 1. Envoy sends to the service information about the HTTP request. -// 2. The service sends back a ProcessingResponse message that directs Envoy -// to either stop processing, continue without it, or send it the -// next chunk of the message body. -// 3. If so requested, Envoy sends the server chunks of the message body, -// or the entire body at once. In either case, the server sends back +// 1. The data plane sends to the service information about the HTTP request. +// 2. The service sends back a ProcessingResponse message that directs the +// data plane to either stop processing, continue without it, or send it +// the next chunk of the message body. +// 3. If so requested, the data plane sends the server chunks of the message +// body, or the entire body at once. In either case, the server sends back // a ProcessingResponse after each message it receives. -// 4. If so requested, Envoy sends the server the HTTP trailers, +// 4. If so requested, the data plane sends the server the HTTP trailers, // and the server sends back a ProcessingResponse. // 5. At this point, request processing is done, and we pick up again -// at step 1 when Envoy receives a response from the upstream server. +// at step 1 when the data plane receives a response from the upstream +// server. // 6. At any point above, if the server closes the gRPC stream cleanly, -// then Envoy proceeds without consulting the server. +// then the data plane proceeds without consulting the server. // 7. At any point above, if the server closes the gRPC stream with an error, -// then Envoy returns a 500 error to the client, unless the filter +// then the data plane returns a 500 error to the client, unless the filter // was configured to ignore errors. // // In other words, the process is a request/response conversation, but // using a gRPC stream to make it easier for the server to // maintain state. service ExternalProcessor { - // This begins the bidirectional stream that Envoy will use to + // This begins the bidirectional stream that the data plane will use to // give the server control over what the filter does. The actual // protocol is described by the ProcessingRequest and ProcessingResponse // messages below. @@ -78,7 +79,7 @@ message ProtocolConfiguration { bool send_body_without_waiting_for_header_response = 3; } -// This represents the different types of messages that Envoy can send +// This represents the different types of messages that the data plane can send // to an external processing server. // [#next-free-field: 12] message ProcessingRequest { @@ -131,7 +132,7 @@ message ProcessingRequest { // The values of properties selected by the ``request_attributes`` // or ``response_attributes`` list in the configuration. Each entry // in the list is populated from the standard - // :ref:`attributes ` supported across Envoy. + // :ref:`attributes ` supported in the data plane. map attributes = 9; // Specify whether the filter that sent this request is running in :ref:`observability_mode @@ -205,8 +206,8 @@ message ProcessingResponse { // may use this to intelligently control how requests are processed // based on the headers and other metadata that they see. // This field is only applicable when servers responding to the header requests. - // If it is set in the response to the body or trailer requests, it will be ignored by Envoy. - // It is also ignored by Envoy when the ext_proc filter config + // If it is set in the response to the body or trailer requests, it will be ignored by the data plane. + // It is also ignored by the data plane when the ext_proc filter config // :ref:`allow_mode_override // ` // is set to false, or @@ -217,16 +218,16 @@ message ProcessingResponse { // When ext_proc server receives a request message, in case it needs more // time to process the message, it sends back a ProcessingResponse message - // with a new timeout value. When Envoy receives this response message, - // it ignores other fields in the response, just stop the original timer, - // which has the timeout value specified in + // with a new timeout value. When the data plane receives this response + // message, it ignores other fields in the response, just stop the original + // timer, which has the timeout value specified in // :ref:`message_timeout // ` // and start a new timer with this ``override_message_timeout`` value and keep the - // Envoy ext_proc filter state machine intact. + // data plane ext_proc filter state machine intact. // Has to be >= 1ms and <= // :ref:`max_message_timeout ` - // Such message can be sent at most once in a particular Envoy ext_proc filter processing state. + // Such message can be sent at most once in a particular data plane ext_proc filter processing state. // To enable this API, one has to set ``max_message_timeout`` to a number >= 1ms. google.protobuf.Duration override_message_timeout = 10; } @@ -259,6 +260,9 @@ message HttpHeaders { message HttpBody { // The contents of the body in the HTTP request/response. Note that in // streaming mode multiple ``HttpBody`` messages may be sent. + // + // In GRPC mode, a separate ``HttpBody`` message will be sent for each + // message in the gRPC stream. bytes body = 1; // If ``true``, this will be the last ``HttpBody`` message that will be sent and no @@ -276,26 +280,26 @@ message HttpTrailers { // The following are messages that may be sent back by the server. -// This message is sent by the external server to Envoy after ``HttpHeaders`` was +// This message is sent by the external server to the data plane after ``HttpHeaders`` was // sent to it. message HeadersResponse { - // Details the modifications (if any) to be made by Envoy to the current + // Details the modifications (if any) to be made by the data plane to the current // request/response. CommonResponse response = 1; } -// This message is sent by the external server to Envoy after ``HttpBody`` was +// This message is sent by the external server to the data plane after ``HttpBody`` was // sent to it. message BodyResponse { - // Details the modifications (if any) to be made by Envoy to the current + // Details the modifications (if any) to be made by the data plane to the current // request/response. CommonResponse response = 1; } -// This message is sent by the external server to Envoy after ``HttpTrailers`` was +// This message is sent by the external server to the data plane after ``HttpTrailers`` was // sent to it. message TrailersResponse { - // Details the modifications (if any) to be made by Envoy to the current + // Details the modifications (if any) to be made by the data plane to the current // request/response trailers. HeaderMutation header_mutation = 1; } @@ -322,10 +326,12 @@ message CommonResponse { // // In other words, this response makes it possible to turn an HTTP GET // into a POST, PUT, or PATCH. + // + // Not supported if the body processing mode is GRPC. CONTINUE_AND_REPLACE = 1; } - // If set, provide additional direction on how the Envoy proxy should + // If set, provide additional direction on how the data plane should // handle the rest of the HTTP filter chain. ResponseStatus status = 1 [(validate.rules).enum = {defined_only: true}]; @@ -354,7 +360,7 @@ message CommonResponse { // Clear the route cache for the current client request. This is necessary // if the remote server modified headers that are used to calculate the route. // This field is ignored in the response direction. This field is also ignored - // if the Envoy ext_proc filter is in the upstream filter chain. + // if the data plane ext_proc filter is in the upstream filter chain. bool clear_route_cache = 5; } @@ -408,7 +414,7 @@ message HeaderMutation { // The body response message corresponding to FULL_DUPLEX_STREAMED body mode. message StreamedBodyResponse { - // The body response chunk that will be passed to the upstream/downstream by Envoy. + // The body response chunk that will be passed to the upstream/downstream by the data plane. bytes body = 1; // The server sets this flag to true if it has received a body request with @@ -417,7 +423,7 @@ message StreamedBodyResponse { bool end_of_stream = 2; } -// This message specifies the body mutation the server sends to Envoy. +// This message specifies the body mutation the server sends to the data plane. message BodyMutation { // The type of mutation for the body. oneof mutation { @@ -430,7 +436,7 @@ message BodyMutation { // Clear the corresponding body chunk. // Should only be used when the corresponding ``BodySendMode`` in the // :ref:`processing_mode ` - // is not set to ``FULL_DUPLEX_STREAMED``. + // is not set to ``FULL_DUPLEX_STREAMED`` or ``GRPC``. // Clear the corresponding body chunk. bool clear_body = 2; From ed81c37ece7e3633c691fe26050daa90c835a73a Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Fri, 11 Jul 2025 00:19:42 +0000 Subject: [PATCH 02/26] add missing import Signed-off-by: Mark D. Roth --- api/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto | 1 + 1 file changed, 1 insertion(+) diff --git a/api/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto b/api/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto index 9887edf5d1366..e97943f012fab 100644 --- a/api/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto +++ b/api/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto @@ -16,6 +16,7 @@ import "google/protobuf/wrappers.proto"; import "xds/annotations/v3/status.proto"; +import "envoy/annotations/deprecation.proto"; import "udpa/annotations/migrate.proto"; import "udpa/annotations/status.proto"; import "validate/validate.proto"; From b30a64bf5470a14091e35049a881df0a7b8d194e Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Fri, 11 Jul 2025 00:44:34 +0000 Subject: [PATCH 03/26] add missing build dep Signed-off-by: Mark D. Roth --- api/envoy/extensions/filters/http/ext_proc/v3/BUILD | 1 + 1 file changed, 1 insertion(+) diff --git a/api/envoy/extensions/filters/http/ext_proc/v3/BUILD b/api/envoy/extensions/filters/http/ext_proc/v3/BUILD index 5bfeeda1b7b89..782bf90b326bb 100644 --- a/api/envoy/extensions/filters/http/ext_proc/v3/BUILD +++ b/api/envoy/extensions/filters/http/ext_proc/v3/BUILD @@ -6,6 +6,7 @@ licenses(["notice"]) # Apache 2 api_proto_package( deps = [ + "//envoy/annotations:pkg", "//envoy/config/common/mutation_rules/v3:pkg", "//envoy/config/core/v3:pkg", "//envoy/type/matcher/v3:pkg", From 28009675dae34ef78ee11a47c0a9c68a0cf78d8c Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Fri, 11 Jul 2025 17:28:47 +0000 Subject: [PATCH 04/26] spelling Signed-off-by: Mark D. Roth --- .../extensions/filters/http/ext_proc/v3/processing_mode.proto | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api/envoy/extensions/filters/http/ext_proc/v3/processing_mode.proto b/api/envoy/extensions/filters/http/ext_proc/v3/processing_mode.proto index 482542f1f31e6..2590b4b017f15 100644 --- a/api/envoy/extensions/filters/http/ext_proc/v3/processing_mode.proto +++ b/api/envoy/extensions/filters/http/ext_proc/v3/processing_mode.proto @@ -109,9 +109,9 @@ message ProcessingMode { FULL_DUPLEX_STREAMED = 4; // [#not-implemented-hide:] - // gRPC traffic. In this mode, the ext_proc client will deframe the + // gRPC traffic. In this mode, the ext_proc client will de-frame the // individual gRPC messages inside the HTTP/2 DATA frames, and as each - // message is deframed, it will be sent to the ext_proc server as a + // message is de-framed, it will be sent to the ext_proc server as a // :ref:`request_body // ` // or :ref:`response_body From 42bd6002067544c93ffb78cad66970d58e3ce8b1 Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Fri, 11 Jul 2025 19:21:15 +0000 Subject: [PATCH 05/26] fix formatting Signed-off-by: Mark D. Roth --- api/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/api/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto b/api/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto index e97943f012fab..6e5ac358c11cd 100644 --- a/api/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto +++ b/api/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto @@ -440,8 +440,7 @@ message ExtProcOverrides { // [#not-implemented-hide:] // Set a different asynchronous processing option than the default. // Deprecated and not implemented. - bool async_mode = 2 - [deprecated = true, (envoy.annotations.deprecated_at_minor_version) = "3.0"]; + bool async_mode = 2 [deprecated = true, (envoy.annotations.deprecated_at_minor_version) = "3.0"]; // [#not-implemented-hide:] // Set different optional attributes than the default setting of the From 532f5265319d875eac06b92b0d09f6c1ce77965b Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Fri, 11 Jul 2025 19:21:58 +0000 Subject: [PATCH 06/26] attempt to fix doc generation Signed-off-by: Mark D. Roth --- api/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto | 1 + .../extensions/filters/http/ext_proc/v3/processing_mode.proto | 1 + 2 files changed, 2 insertions(+) diff --git a/api/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto b/api/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto index 6e5ac358c11cd..9103ca2b3489d 100644 --- a/api/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto +++ b/api/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto @@ -66,6 +66,7 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE; // processor. There will be exactly one gRPC message in each message // sent to the external processor. // * ``NONE``: Body will not be sent to the external processor. +// // * Request trailers: Delivered if they are present and if the trailer mode is set // to ``SEND``. // * Response headers: Contains the headers from the HTTP response. Keep in mind diff --git a/api/envoy/extensions/filters/http/ext_proc/v3/processing_mode.proto b/api/envoy/extensions/filters/http/ext_proc/v3/processing_mode.proto index 2590b4b017f15..ba10e3ce7bc67 100644 --- a/api/envoy/extensions/filters/http/ext_proc/v3/processing_mode.proto +++ b/api/envoy/extensions/filters/http/ext_proc/v3/processing_mode.proto @@ -106,6 +106,7 @@ message ProcessingMode { // :ref:`StreamedBodyResponse ` // to the client in the body response. // * The client will stream the body chunks in the responses from the server to the upstream/downstream as they arrive. + FULL_DUPLEX_STREAMED = 4; // [#not-implemented-hide:] From ace4e47b0af5e451e12b09bb063ebf8dd6f4b9e1 Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Wed, 10 Sep 2025 23:31:30 +0000 Subject: [PATCH 07/26] attempt to fix RST formatting Signed-off-by: Mark D. Roth --- .../filters/http/ext_proc/v3/ext_proc.proto | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/api/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto b/api/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto index cad6913baac13..0846e733a755f 100644 --- a/api/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto +++ b/api/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto @@ -58,14 +58,14 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE; // * Request headers: Contains the headers from the original HTTP request. // * Request body: If the body is present, the behavior depends on the // body send mode: -// * ``BUFFERED`` or ``BUFFERED_PARTIAL``: Entire body is sent to the -// external processor in a single message. -// * ``STREAMED`` or ``FULL_DUPLEX_STREAMED``: Body will be split across -// multiple messages sent to the external processor. -// * ``GRPC``: As each gRPC message arrives, it will be sent to the external -// processor. There will be exactly one gRPC message in each message -// sent to the external processor. -// * ``NONE``: Body will not be sent to the external processor. +// * ``BUFFERED`` or ``BUFFERED_PARTIAL``: Entire body is sent to the +// external processor in a single message. +// * ``STREAMED`` or ``FULL_DUPLEX_STREAMED``: Body will be split across +// multiple messages sent to the external processor. +// * ``GRPC``: As each gRPC message arrives, it will be sent to the external +// processor. There will be exactly one gRPC message in each message +// sent to the external processor. +// * ``NONE``: Body will not be sent to the external processor. // // * Request trailers: Delivered if they are present and if the trailer mode is set // to ``SEND``. From 8c307bcd76972584a0a96c28a291afe0647bec5a Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Wed, 10 Sep 2025 23:32:20 +0000 Subject: [PATCH 08/26] fix wording Signed-off-by: Mark D. Roth --- api/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto b/api/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto index 0846e733a755f..ef0da9717636c 100644 --- a/api/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto +++ b/api/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto @@ -58,7 +58,7 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE; // * Request headers: Contains the headers from the original HTTP request. // * Request body: If the body is present, the behavior depends on the // body send mode: -// * ``BUFFERED`` or ``BUFFERED_PARTIAL``: Entire body is sent to the +// * ``BUFFERED`` or ``BUFFERED_PARTIAL``: Body is sent to the // external processor in a single message. // * ``STREAMED`` or ``FULL_DUPLEX_STREAMED``: Body will be split across // multiple messages sent to the external processor. From bc9a0ad97da9d9f3114a6dee197274590791745d Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Fri, 12 Sep 2025 00:27:30 +0000 Subject: [PATCH 09/26] clarify streaming behavior of GRPC body send mode Signed-off-by: Mark D. Roth --- .../extensions/filters/http/ext_proc/v3/processing_mode.proto | 2 ++ 1 file changed, 2 insertions(+) diff --git a/api/envoy/extensions/filters/http/ext_proc/v3/processing_mode.proto b/api/envoy/extensions/filters/http/ext_proc/v3/processing_mode.proto index ba10e3ce7bc67..6359624317d5f 100644 --- a/api/envoy/extensions/filters/http/ext_proc/v3/processing_mode.proto +++ b/api/envoy/extensions/filters/http/ext_proc/v3/processing_mode.proto @@ -119,6 +119,8 @@ message ProcessingMode { // `. // If the ext_proc server modifies the body, that modified body will // be used to replace the gRPC message in the stream. + // In this mode, the client will send body and trailers to the server as + // they arrive. GRPC = 5; } From 975e8491046cb58c2def0a075ec52d0afac565e5 Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Fri, 12 Sep 2025 00:28:35 +0000 Subject: [PATCH 10/26] add comment about timeout behavior vs. body mode, and send_body_without_waiting_for_header_response does not work for GRPC Signed-off-by: Mark D. Roth --- .../extensions/filters/http/ext_proc/v3/ext_proc.proto | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/api/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto b/api/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto index ef0da9717636c..6ff64975e7d66 100644 --- a/api/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto +++ b/api/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto @@ -213,8 +213,9 @@ message ExternalProcessor { // response, it will reset this timer, and will stop processing and return // an error (subject to the processing mode) if the timer expires before a // matching response is received. There is no timeout when the filter is - // running in observability mode. Zero is a valid config which means the - // timer will be triggered immediately. If not configured, default is 200 + // running in observability mode or when the body send mode is + // ``FULL_DUPLEX_STREAMED`` or ``GRPC``. Zero is a valid config which means + // the timer will be triggered immediately. If not configured, default is 200 // milliseconds. google.protobuf.Duration message_timeout = 7 [(validate.rules).duration = { lte {seconds: 3600} @@ -320,7 +321,7 @@ message ExternalProcessor { google.protobuf.Duration deferred_close_timeout = 19; // Send body to the side stream server once it arrives without waiting for the header response from that server. - // It only works for ``STREAMED`` and ``GRPC`` body processing modes. For any other body + // It only works for ``STREAMED`` body processing mode. For any other body // processing modes, it is ignored. // The server has two options upon receiving a header request: // From e8afc4b9216e0bd7f37fbb3b1a1a178b48b75dcc Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Fri, 12 Sep 2025 00:36:38 +0000 Subject: [PATCH 11/26] try to fix formatting Signed-off-by: Mark D. Roth --- .../filters/http/ext_proc/v3/ext_proc.proto | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/api/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto b/api/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto index 6ff64975e7d66..b1ee98717f46e 100644 --- a/api/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto +++ b/api/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto @@ -57,16 +57,12 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE; // // * Request headers: Contains the headers from the original HTTP request. // * Request body: If the body is present, the behavior depends on the -// body send mode: -// * ``BUFFERED`` or ``BUFFERED_PARTIAL``: Body is sent to the -// external processor in a single message. -// * ``STREAMED`` or ``FULL_DUPLEX_STREAMED``: Body will be split across -// multiple messages sent to the external processor. -// * ``GRPC``: As each gRPC message arrives, it will be sent to the external -// processor. There will be exactly one gRPC message in each message -// sent to the external processor. -// * ``NONE``: Body will not be sent to the external processor. -// +// body send mode. In ``BUFFERED`` or ``BUFFERED_PARTIAL`` mode, the body is sent to the external +// processor in a single message. In ``STREAMED`` or ``FULL_DUPLEX_STREAMED`` mode, the body will +// be split across multiple messages sent to the external processor. In ``GRPC`` mode, as each +// gRPC message arrives, it will be sent to the external processor (there will be exactly one +// gRPC message in each message sent to the external processor). In ``NONE`` mode, the body will +// not be sent to the external processor. // * Request trailers: Delivered if they are present and if the trailer mode is set // to ``SEND``. // * Response headers: Contains the headers from the HTTP response. Keep in mind From 532c31d5dad2c5c425d015d3ec59f8241ccafda0 Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Fri, 12 Sep 2025 16:45:37 +0000 Subject: [PATCH 12/26] GRPC mode will support timers, and note that FULL_DUPLEX_STREAMED does not support mode override Signed-off-by: Mark D. Roth --- api/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/api/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto b/api/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto index b1ee98717f46e..936de646d787a 100644 --- a/api/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto +++ b/api/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto @@ -210,8 +210,8 @@ message ExternalProcessor { // an error (subject to the processing mode) if the timer expires before a // matching response is received. There is no timeout when the filter is // running in observability mode or when the body send mode is - // ``FULL_DUPLEX_STREAMED`` or ``GRPC``. Zero is a valid config which means - // the timer will be triggered immediately. If not configured, default is 200 + // ``FULL_DUPLEX_STREAMED``. Zero is a valid config which means the timer + // will be triggered immediately. If not configured, default is 200 // milliseconds. google.protobuf.Duration message_timeout = 7 [(validate.rules).duration = { lte {seconds: 3600} @@ -257,6 +257,7 @@ message ExternalProcessor { // can be overridden by the response message from the external processing server // :ref:`mode_override `. // If not set, ``mode_override`` API in the response message will be ignored. + // Mode override is not supported if the body send mode is ``FULL_DUPLEX_STREAMED``. bool allow_mode_override = 14; // If set to true, ignore the From cd3b71f6f69b96848d13b6beb9f3c08da0d7709b Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Fri, 12 Sep 2025 17:07:15 +0000 Subject: [PATCH 13/26] [xDS] improve documentation for ext_proc Signed-off-by: Mark D. Roth --- .../extensions/filters/http/ext_proc/v3/BUILD | 1 + .../filters/http/ext_proc/v3/ext_proc.proto | 74 ++++++++++--------- .../http/ext_proc/v3/processing_mode.proto | 15 ++-- .../ext_proc/v3/external_processor.proto | 68 ++++++++--------- 4 files changed, 81 insertions(+), 77 deletions(-) diff --git a/api/envoy/extensions/filters/http/ext_proc/v3/BUILD b/api/envoy/extensions/filters/http/ext_proc/v3/BUILD index 5bfeeda1b7b89..782bf90b326bb 100644 --- a/api/envoy/extensions/filters/http/ext_proc/v3/BUILD +++ b/api/envoy/extensions/filters/http/ext_proc/v3/BUILD @@ -6,6 +6,7 @@ licenses(["notice"]) # Apache 2 api_proto_package( deps = [ + "//envoy/annotations:pkg", "//envoy/config/common/mutation_rules/v3:pkg", "//envoy/config/core/v3:pkg", "//envoy/type/matcher/v3:pkg", diff --git a/api/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto b/api/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto index 2187c4547c61c..52d9cd282792a 100644 --- a/api/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto +++ b/api/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto @@ -16,6 +16,7 @@ import "google/protobuf/wrappers.proto"; import "xds/annotations/v3/status.proto"; +import "envoy/annotations/deprecation.proto"; import "udpa/annotations/migrate.proto"; import "udpa/annotations/status.proto"; import "validate/validate.proto"; @@ -48,8 +49,6 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE; // // * Whether it receives the response message at all. // * Whether it receives the message body at all, in separate chunks, or as a single buffer. -// * Whether subsequent HTTP requests are transmitted synchronously or whether they are -// sent asynchronously. // * To modify request or response trailers if they already exist. // // The filter supports up to six different processing steps. Each is represented by @@ -57,9 +56,11 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE; // processor must send a matching response. // // * Request headers: Contains the headers from the original HTTP request. -// * Request body: Delivered if they are present and sent in a single message if -// the ``BUFFERED`` or ``BUFFERED_PARTIAL`` mode is chosen, in multiple messages if the -// ``STREAMED`` mode is chosen, and not at all otherwise. +// * Request body: If the body is present, the behavior depends on the +// body send mode. In ``BUFFERED`` or ``BUFFERED_PARTIAL`` mode, the body is sent to the external +// processor in a single message. In ``STREAMED`` or ``FULL_DUPLEX_STREAMED`` mode, the body will +// be split across multiple messages sent to the external processor. In ``NONE`` mode, the body +// will not be sent to the external processor. // * Request trailers: Delivered if they are present and if the trailer mode is set // to ``SEND``. // * Response headers: Contains the headers from the HTTP response. Keep in mind @@ -75,7 +76,7 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE; // from the external processor. The latter is only enabled if ``allow_mode_override`` is // set to true. This way, a processor may, for example, use information // in the request header to determine whether the message body must be examined, or whether -// the proxy should simply stream it straight through. +// the data plane should simply stream it straight through. // // All of this together allows a server to process the filter traffic in fairly // sophisticated ways. For example: @@ -84,12 +85,8 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE; // on the content of the headers. // * A server may choose to immediately reject some messages based on their HTTP // headers (or other dynamic metadata) and more carefully examine others. -// * A server may asynchronously monitor traffic coming through the filter by inspecting -// headers, bodies, or both, and then decide to switch to a synchronous processing -// mode, either permanently or temporarily. // -// The protocol itself is based on a bidirectional gRPC stream. Envoy will send the -// server +// The protocol itself is based on a bidirectional gRPC stream. The data plane will send the server // :ref:`ProcessingRequest ` // messages, and the server must reply with // :ref:`ProcessingResponse `. @@ -124,7 +121,6 @@ message ExternalProcessor { reserved "async_mode"; // Configuration for the gRPC service that the filter will communicate with. - // The filter supports both the "Envoy" and "Google" gRPC clients. // Only one of ``grpc_service`` or ``http_service`` can be set. // It is required that one of them must be set. config.core.v3.GrpcService grpc_service = 1 @@ -140,14 +136,14 @@ message ExternalProcessor { // cannot be configured to send any body or trailers. i.e., ``http_service`` only supports // sending request or response headers to the side stream server. // - // With this configuration, Envoy behavior: + // With this configuration, the data plane behavior is: // // 1. The headers are first put in a proto message // :ref:`ProcessingRequest `. // // 2. This proto message is then transcoded into a JSON text. // - // 3. Envoy then sends an HTTP POST message with content-type as "application/json", + // 3. The data plane then sends an HTTP POST message with content-type as "application/json", // and this JSON text as body to the side stream server. // // After the side-stream receives this HTTP request message, it is expected to do as follows: @@ -160,7 +156,7 @@ message ExternalProcessor { // // 3. It converts the ``ProcessingResponse`` proto message into a JSON text. // - // 4. It then sends an HTTP response back to Envoy with status code as ``"200"``, + // 4. It then sends an HTTP response back to the data plane with status code as ``"200"``, // ``content-type`` as ``"application/json"`` and sets the JSON text as the body. // ExtProcHttpService http_service = 20 [ @@ -190,28 +186,31 @@ message ExternalProcessor { // sent. See ``ProcessingMode`` for details. ProcessingMode processing_mode = 3; - // Envoy provides a number of :ref:`attributes ` + // The data plane provides a number of :ref:`attributes ` // for expressive policies. Each attribute name provided in this field will be - // matched against that list and populated in the ``request_headers`` message. + // matched against that list and populated in the + // :ref:`ProcessingRequest.attributes ` field. // See the :ref:`attribute documentation ` // for the list of supported attributes and their types. repeated string request_attributes = 5; - // Envoy provides a number of :ref:`attributes ` + // The data plane provides a number of :ref:`attributes ` // for expressive policies. Each attribute name provided in this field will be - // matched against that list and populated in the ``response_headers`` message. + // matched against that list and populated in the + // :ref:`ProcessingRequest.attributes ` field. // See the :ref:`attribute documentation ` // for the list of supported attributes and their types. repeated string response_attributes = 6; - // Specifies the timeout for each individual message sent on the stream and - // when the filter is running in synchronous mode. Whenever the proxy sends - // a message on the stream that requires a response, it will reset this timer, - // and will stop processing and return an error (subject to the processing mode) - // if the timer expires before a matching response is received. There is no - // timeout when the filter is running in asynchronous mode. Zero is a valid - // config which means the timer will be triggered immediately. If not - // configured, default is 200 milliseconds. + // Specifies the timeout for each individual message sent on the stream. + // Whenever the data plane sends a message on the stream that requires a + // response, it will reset this timer, and will stop processing and return + // an error (subject to the processing mode) if the timer expires before a + // matching response is received. There is no timeout when the filter is + // running in observability mode or when the body send mode is + // ``FULL_DUPLEX_STREAMED``. Zero is a valid config which means the timer + // will be triggered immediately. If not configured, default is 200 + // milliseconds. google.protobuf.Duration message_timeout = 7 [(validate.rules).duration = { lte {seconds: 3600} gte {} @@ -228,7 +227,7 @@ message ExternalProcessor { // :ref:`header_prefix ` // (which is usually "x-envoy"). // Note that changing headers such as "host" or ":authority" may not in itself - // change Envoy's routing decision, as routes can be cached. To also force the + // change the data plane's routing decision, as routes can be cached. To also force the // route to be recomputed, set the // :ref:`clear_route_cache ` // field to true in the same response. @@ -256,6 +255,7 @@ message ExternalProcessor { // can be overridden by the response message from the external processing server // :ref:`mode_override `. // If not set, ``mode_override`` API in the response message will be ignored. + // Mode override is not supported if the body send mode is ``FULL_DUPLEX_STREAMED``. bool allow_mode_override = 14; // If set to true, ignore the @@ -270,10 +270,10 @@ message ExternalProcessor { // If true, send each part of the HTTP request or response specified by ``ProcessingMode`` // without pausing on filter chain iteration. It is "Send and Go" mode that can be used - // by external processor to observe Envoy data and status. In this mode: + // by external processor to observe the request's data and status. In this mode: // - // 1. Only ``STREAMED`` body processing mode is supported and any other body processing modes will be - // ignored. ``NONE`` mode (i.e., skip body processing) will still work as expected. + // 1. Only ``STREAMED`` and ``NONE`` body processing modes are supported; for any other body + // processing mode, the body will not be sent. // // 2. External processor should not send back processing response, as any responses will be ignored. // This also means that @@ -310,12 +310,13 @@ message ExternalProcessor { // Specifies the deferred closure timeout for gRPC stream that connects to external processor. Currently, the deferred stream closure // is only used in :ref:`observability_mode `. // In observability mode, gRPC streams may be held open to the external processor longer than the lifetime of the regular client to - // backend stream lifetime. In this case, Envoy will eventually timeout the external processor stream according to this time limit. + // backend stream lifetime. In this case, the data plane will eventually timeout the external processor stream according to this time limit. // The default value is 5000 milliseconds (5 seconds) if not specified. google.protobuf.Duration deferred_close_timeout = 19; // Send body to the side stream server once it arrives without waiting for the header response from that server. - // It only works for ``STREAMED`` body processing mode. For any other body processing modes, it is ignored. + // It only works for ``STREAMED`` body processing mode. For any other body + // processing modes, it is ignored. // The server has two options upon receiving a header request: // // 1. Instant Response: send the header response as soon as the header request is received. @@ -324,9 +325,9 @@ message ExternalProcessor { // // In all scenarios, the header-body ordering must always be maintained. // - // If enabled Envoy will ignore the + // If enabled the data plane will ignore the // :ref:`mode_override ` - // value that the server sends in the header response. This is because Envoy may have already + // value that the server sends in the header response. This is because the data plane may have already // sent the body to the server, prior to processing the header response. bool send_body_without_waiting_for_header_response = 21; @@ -430,7 +431,8 @@ message ExtProcOverrides { // [#not-implemented-hide:] // Set a different asynchronous processing option than the default. - bool async_mode = 2; + // Deprecated and not implemented. + bool async_mode = 2 [deprecated = true, (envoy.annotations.deprecated_at_minor_version) = "3.0"]; // [#not-implemented-hide:] // Set different optional attributes than the default setting of the diff --git a/api/envoy/extensions/filters/http/ext_proc/v3/processing_mode.proto b/api/envoy/extensions/filters/http/ext_proc/v3/processing_mode.proto index 467320d4a417b..ccf84ddee3e8d 100644 --- a/api/envoy/extensions/filters/http/ext_proc/v3/processing_mode.proto +++ b/api/envoy/extensions/filters/http/ext_proc/v3/processing_mode.proto @@ -65,8 +65,7 @@ message ProcessingMode { // Do not send the body at all. This is the default. NONE = 0; - // Stream the body to the server in pieces as they arrive at the - // proxy. + // Stream the body to the server in pieces as they are seen. STREAMED = 1; // Buffer the message body in memory and send the entire body at once. @@ -79,11 +78,11 @@ message ProcessingMode { // up to the buffer limit will be sent. BUFFERED_PARTIAL = 3; - // Envoy streams the body to the server in pieces as they arrive. + // The ext_proc client streams the body to the server in pieces as they arrive. // // 1) The server may choose to buffer any number chunks of data before processing them. // After it finishes buffering, the server processes the buffered data. Then it splits the processed - // data into any number of chunks, and streams them back to Envoy one by one. + // data into any number of chunks, and streams them back to the client one by one. // The server may continuously do so until the complete body is processed. // The individual response chunk size is recommended to be no greater than 64K bytes, or // :ref:`max_receive_message_length ` @@ -98,15 +97,15 @@ message ProcessingMode { // // In this body mode: // * The corresponding trailer mode has to be set to ``SEND``. - // * Envoy will send body and trailers (if present) to the server as they arrive. + // * The client will send body and trailers (if present) to the server as they arrive. // Sending the trailers (if present) is to inform the server the complete body arrives. - // In case there are no trailers, then Envoy will set + // In case there are no trailers, then the client will set // :ref:`end_of_stream ` // to true as part of the last body chunk request to notify the server that no other data is to be sent. // * The server needs to send // :ref:`StreamedBodyResponse ` - // to Envoy in the body response. - // * Envoy will stream the body chunks in the responses from the server to the upstream/downstream as they arrive. + // to the client in the body response. + // * The client will stream the body chunks in the responses from the server to the upstream/downstream as they arrive. FULL_DUPLEX_STREAMED = 4; } diff --git a/api/envoy/service/ext_proc/v3/external_processor.proto b/api/envoy/service/ext_proc/v3/external_processor.proto index e77d60d0b9700..406c5c195a2a7 100644 --- a/api/envoy/service/ext_proc/v3/external_processor.proto +++ b/api/envoy/service/ext_proc/v3/external_processor.proto @@ -27,29 +27,31 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE; // as part of a filter chain. // The overall external processing protocol works like this: // -// 1. Envoy sends to the service information about the HTTP request. -// 2. The service sends back a ProcessingResponse message that directs Envoy -// to either stop processing, continue without it, or send it the -// next chunk of the message body. -// 3. If so requested, Envoy sends the server the message body in chunks, -// or the entire body at once. In either case, the server may send back -// a ProcessingResponse for each message it receives, or wait for certain amount -// of body chunks received before streams back the ProcessingResponse messages. -// 4. If so requested, Envoy sends the server the HTTP trailers, +// 1. The data plane sends to the service information about the HTTP request. +// 2. The service sends back a ProcessingResponse message that directs +// the data plane to either stop processing, continue without it, or send +// it the next chunk of the message body. +// 3. If so requested, the data plane sends the server the message body in +// chunks, or the entire body at once. In either case, the server may send +// back a ProcessingResponse for each message it receives, or wait for +// a certain amount of body chunks received before streaming back the +// ProcessingResponse messages. +// 4. If so requested, the data plane sends the server the HTTP trailers, // and the server sends back a ProcessingResponse. // 5. At this point, request processing is done, and we pick up again -// at step 1 when Envoy receives a response from the upstream server. +// at step 1 when the data plane receives a response from the upstream +// server. // 6. At any point above, if the server closes the gRPC stream cleanly, -// then Envoy proceeds without consulting the server. +// then the data plane proceeds without consulting the server. // 7. At any point above, if the server closes the gRPC stream with an error, -// then Envoy returns a 500 error to the client, unless the filter +// then the data plane returns a 500 error to the client, unless the filter // was configured to ignore errors. // // In other words, the process is a request/response conversation, but // using a gRPC stream to make it easier for the server to // maintain state. service ExternalProcessor { - // This begins the bidirectional stream that Envoy will use to + // This begins the bidirectional stream that the data plane will use to // give the server control over what the filter does. The actual // protocol is described by the ProcessingRequest and ProcessingResponse // messages below. @@ -79,7 +81,7 @@ message ProtocolConfiguration { bool send_body_without_waiting_for_header_response = 3; } -// This represents the different types of messages that Envoy can send +// This represents the different types of messages that the data plane can send // to an external processing server. // [#next-free-field: 12] message ProcessingRequest { @@ -132,7 +134,7 @@ message ProcessingRequest { // The values of properties selected by the ``request_attributes`` // or ``response_attributes`` list in the configuration. Each entry // in the list is populated from the standard - // :ref:`attributes ` supported across Envoy. + // :ref:`attributes ` supported in the data plane. map attributes = 9; // Specify whether the filter that sent this request is running in :ref:`observability_mode @@ -153,7 +155,7 @@ message ProcessingRequest { ProtocolConfiguration protocol_config = 11; } -// This represents the different types of messages the server may send back to Envoy +// This represents the different types of messages the server may send back to the data plane // when the ``observability_mode`` field in the received ProcessingRequest is set to false. // // * If the corresponding ``BodySendMode`` in the @@ -212,8 +214,8 @@ message ProcessingResponse { // may use this to intelligently control how requests are processed // based on the headers and other metadata that they see. // This field is only applicable when servers responding to the header requests. - // If it is set in the response to the body or trailer requests, it will be ignored by Envoy. - // It is also ignored by Envoy when the ext_proc filter config + // If it is set in the response to the body or trailer requests, it will be ignored by the data plane. + // It is also ignored by the data plane when the ext_proc filter config // :ref:`allow_mode_override // ` // is set to false, or @@ -224,16 +226,16 @@ message ProcessingResponse { // When ext_proc server receives a request message, in case it needs more // time to process the message, it sends back a ProcessingResponse message - // with a new timeout value. When Envoy receives this response message, - // it ignores other fields in the response, just stop the original timer, - // which has the timeout value specified in + // with a new timeout value. When the data plane receives this response + // message, it ignores other fields in the response, just stop the original + // timer, which has the timeout value specified in // :ref:`message_timeout // ` // and start a new timer with this ``override_message_timeout`` value and keep the - // Envoy ext_proc filter state machine intact. + // data plane ext_proc filter state machine intact. // Has to be >= 1ms and <= // :ref:`max_message_timeout ` - // Such message can be sent at most once in a particular Envoy ext_proc filter processing state. + // Such message can be sent at most once in a particular data plane ext_proc filter processing state. // To enable this API, one has to set ``max_message_timeout`` to a number >= 1ms. google.protobuf.Duration override_message_timeout = 10; } @@ -283,26 +285,26 @@ message HttpTrailers { // The following are messages that may be sent back by the server. -// This message is sent by the external server to Envoy after ``HttpHeaders`` was +// This message is sent by the external server to the data plane after ``HttpHeaders`` was // sent to it. message HeadersResponse { - // Details the modifications (if any) to be made by Envoy to the current + // Details the modifications (if any) to be made by the data plane to the current // request/response. CommonResponse response = 1; } -// This message is sent by the external server to Envoy after ``HttpBody`` was +// This message is sent by the external server to the data plane after ``HttpBody`` was // sent to it. message BodyResponse { - // Details the modifications (if any) to be made by Envoy to the current + // Details the modifications (if any) to be made by the data plane to the current // request/response. CommonResponse response = 1; } -// This message is sent by the external server to Envoy after ``HttpTrailers`` was +// This message is sent by the external server to the data plane after ``HttpTrailers`` was // sent to it. message TrailersResponse { - // Details the modifications (if any) to be made by Envoy to the current + // Details the modifications (if any) to be made by the data plane to the current // request/response trailers. HeaderMutation header_mutation = 1; } @@ -332,7 +334,7 @@ message CommonResponse { CONTINUE_AND_REPLACE = 1; } - // If set, provide additional direction on how the Envoy proxy should + // If set, provide additional direction on how the data plane should // handle the rest of the HTTP filter chain. ResponseStatus status = 1 [(validate.rules).enum = {defined_only: true}]; @@ -361,7 +363,7 @@ message CommonResponse { // Clear the route cache for the current client request. This is necessary // if the remote server modified headers that are used to calculate the route. // This field is ignored in the response direction. This field is also ignored - // if the Envoy ext_proc filter is in the upstream filter chain. + // if the data plane ext_proc filter is in the upstream filter chain. bool clear_route_cache = 5; } @@ -415,7 +417,7 @@ message HeaderMutation { // The body response message corresponding to FULL_DUPLEX_STREAMED body mode. message StreamedBodyResponse { - // The body response chunk that will be passed to the upstream/downstream by Envoy. + // The body response chunk that will be passed to the upstream/downstream by the data plane. bytes body = 1; // The server sets this flag to true if it has received a body request with @@ -424,7 +426,7 @@ message StreamedBodyResponse { bool end_of_stream = 2; } -// This message specifies the body mutation the server sends to Envoy. +// This message specifies the body mutation the server sends to the data plane. message BodyMutation { // The type of mutation for the body. oneof mutation { From 4b7f6f5d806135c1f4f0aca22d433f7735c4c8e4 Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Fri, 12 Sep 2025 17:26:32 +0000 Subject: [PATCH 14/26] clarify wording Signed-off-by: Mark D. Roth --- api/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/api/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto b/api/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto index 936de646d787a..dc972b7bfe2d6 100644 --- a/api/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto +++ b/api/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto @@ -274,9 +274,8 @@ message ExternalProcessor { // without pausing on filter chain iteration. It is "Send and Go" mode that can be used // by external processor to observe the request's data and status. In this mode: // - // 1. Only ``STREAMED`` and ``GRPC`` body processing modes are supported and any other body - // processing modes will be ignored. ``NONE`` mode (i.e., skip body processing) will still - // work as expected. + // 1. Only ``STREAMED``, ``GRPC``, and ``NONE`` body processing modes are supported; for any + // other body processing mode, the body will not be sent. // // 2. External processor should not send back processing response, as any responses will be ignored. // This also means that From e7cbd4dc7b19c83cf11ca850112320df44ab695e Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Fri, 12 Sep 2025 18:10:24 +0000 Subject: [PATCH 15/26] formatting and wording tweak Signed-off-by: Mark D. Roth --- api/envoy/service/ext_proc/v3/external_processor.proto | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/api/envoy/service/ext_proc/v3/external_processor.proto b/api/envoy/service/ext_proc/v3/external_processor.proto index 05bba30d3bba8..71a776f300686 100644 --- a/api/envoy/service/ext_proc/v3/external_processor.proto +++ b/api/envoy/service/ext_proc/v3/external_processor.proto @@ -269,8 +269,8 @@ message HttpBody { // The contents of the body in the HTTP request/response. Note that in // streaming mode multiple ``HttpBody`` messages may be sent. // - // In GRPC mode, a separate ``HttpBody`` message will be sent for each - // message in the gRPC stream. + // In ``GRPC`` body send mode, a separate ``HttpBody`` message will be + // sent for each message in the gRPC stream. bytes body = 1; // If ``true``, this will be the last ``HttpBody`` message that will be sent and no @@ -335,7 +335,7 @@ message CommonResponse { // In other words, this response makes it possible to turn an HTTP GET // into a POST, PUT, or PATCH. // - // Not supported if the body processing mode is GRPC. + // Not supported if the body send mode is ``GRPC``. CONTINUE_AND_REPLACE = 1; } From aa8d3cc97a67e765245fdb7cf271822bd59e8ad2 Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Fri, 12 Sep 2025 22:27:16 +0000 Subject: [PATCH 16/26] GRPC mode uses StreamedBodyResponse Signed-off-by: Mark D. Roth --- api/envoy/service/ext_proc/v3/external_processor.proto | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/api/envoy/service/ext_proc/v3/external_processor.proto b/api/envoy/service/ext_proc/v3/external_processor.proto index 71a776f300686..625a5e669bf01 100644 --- a/api/envoy/service/ext_proc/v3/external_processor.proto +++ b/api/envoy/service/ext_proc/v3/external_processor.proto @@ -420,9 +420,11 @@ message HeaderMutation { repeated string remove_headers = 2; } -// The body response message corresponding to FULL_DUPLEX_STREAMED body mode. +// The body response message corresponding to ``FULL_DUPLEX_STREAMED`` or ``GRPC`` body modes. message StreamedBodyResponse { - // The body response chunk that will be passed to the upstream/downstream by the data plane. + // In ``FULL_DUPLEX_STREAMED`` body send mode, contains the body response chunk that will be + // passed to the upstream/downstream by the data plane. In ``GRPC`` body send mode, contains + // a serialized gRPC message to be passed to the upstream/downstream by the data plane. bytes body = 1; // The server sets this flag to true if it has received a body request with @@ -438,7 +440,7 @@ message BodyMutation { // The entire body to replace. // Should only be used when the corresponding ``BodySendMode`` in the // :ref:`processing_mode ` - // is not set to ``FULL_DUPLEX_STREAMED``. + // is not set to ``FULL_DUPLEX_STREAMED`` or ``GRPC``. bytes body = 1; // Clear the corresponding body chunk. @@ -450,7 +452,7 @@ message BodyMutation { // Must be used when the corresponding ``BodySendMode`` in the // :ref:`processing_mode ` - // is set to ``FULL_DUPLEX_STREAMED``. + // is set to ``FULL_DUPLEX_STREAMED`` or ``GRPC``. StreamedBodyResponse streamed_response = 3 [(xds.annotations.v3.field_status).work_in_progress = true]; } From 6932eb611038672a7fe4f73a59dfa15106493a36 Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Fri, 12 Sep 2025 22:37:16 +0000 Subject: [PATCH 17/26] clarify GRPC mode description, and note that message timeouts are not supported in that mode Signed-off-by: Mark D. Roth --- .../extensions/filters/http/ext_proc/v3/ext_proc.proto | 6 +++--- .../filters/http/ext_proc/v3/processing_mode.proto | 8 ++++++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/api/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto b/api/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto index dc972b7bfe2d6..cef6d260f683f 100644 --- a/api/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto +++ b/api/envoy/extensions/filters/http/ext_proc/v3/ext_proc.proto @@ -210,9 +210,9 @@ message ExternalProcessor { // an error (subject to the processing mode) if the timer expires before a // matching response is received. There is no timeout when the filter is // running in observability mode or when the body send mode is - // ``FULL_DUPLEX_STREAMED``. Zero is a valid config which means the timer - // will be triggered immediately. If not configured, default is 200 - // milliseconds. + // ``FULL_DUPLEX_STREAMED`` or ``GRPC``. Zero is a valid config which means + // the timer will be triggered immediately. If not configured, default is + // 200 milliseconds. google.protobuf.Duration message_timeout = 7 [(validate.rules).duration = { lte {seconds: 3600} gte {} diff --git a/api/envoy/extensions/filters/http/ext_proc/v3/processing_mode.proto b/api/envoy/extensions/filters/http/ext_proc/v3/processing_mode.proto index 6359624317d5f..a987675f83c78 100644 --- a/api/envoy/extensions/filters/http/ext_proc/v3/processing_mode.proto +++ b/api/envoy/extensions/filters/http/ext_proc/v3/processing_mode.proto @@ -117,8 +117,12 @@ message ProcessingMode { // ` // or :ref:`response_body // `. - // If the ext_proc server modifies the body, that modified body will - // be used to replace the gRPC message in the stream. + // The ext_proc server will stream back individual gRPC messages in the + // :ref:`StreamedBodyResponse ` + // field, but the number of messages sent by the ext_proc server + // does not need to equal the number of messages sent by the data + // plane. This allows the ext_proc server to change the number of + // messages sent on the stream. // In this mode, the client will send body and trailers to the server as // they arrive. GRPC = 5; From 0015fbd525e874e8afcb9193c6fca2e06f0038e3 Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Fri, 12 Sep 2025 22:41:18 +0000 Subject: [PATCH 18/26] ext_proc server can inject EOS on gRPC client message Signed-off-by: Mark D. Roth --- api/envoy/service/ext_proc/v3/external_processor.proto | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/api/envoy/service/ext_proc/v3/external_processor.proto b/api/envoy/service/ext_proc/v3/external_processor.proto index 625a5e669bf01..35471c6fe0da0 100644 --- a/api/envoy/service/ext_proc/v3/external_processor.proto +++ b/api/envoy/service/ext_proc/v3/external_processor.proto @@ -430,6 +430,10 @@ message StreamedBodyResponse { // The server sets this flag to true if it has received a body request with // :ref:`end_of_stream ` set to true, // and this is the last chunk of body responses. + // Note that in ``GRPC`` body send mode, this allows the ext_proc + // server to tell the data plane to send a half close after a client + // message, which will result in discarding any other messages sent by + // the client application. bool end_of_stream = 2; } From 708120f5a8a21465b45d0a87d12fc96e89b8214b Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Fri, 12 Sep 2025 22:57:26 +0000 Subject: [PATCH 19/26] add a safe way for ext_proc server to close the stream with OK status Signed-off-by: Mark D. Roth --- .../service/ext_proc/v3/external_processor.proto | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/api/envoy/service/ext_proc/v3/external_processor.proto b/api/envoy/service/ext_proc/v3/external_processor.proto index 35471c6fe0da0..96d3e2d1204ff 100644 --- a/api/envoy/service/ext_proc/v3/external_processor.proto +++ b/api/envoy/service/ext_proc/v3/external_processor.proto @@ -164,7 +164,7 @@ message ProcessingRequest { // the server must send back exactly one ProcessingResponse message. // * If it is set to ``FULL_DUPLEX_STREAMED``, the server must follow the API defined // for this mode to send the ProcessingResponse messages. -// [#next-free-field: 11] +// [#next-free-field: 12] message ProcessingResponse { // The response type that is sent by the server. oneof response { @@ -224,6 +224,19 @@ message ProcessingResponse { // is set to true. envoy.extensions.filters.http.ext_proc.v3.ProcessingMode mode_override = 9; + // [#not-implemented-hide:] + // Used only in ``FULL_DUPLEX_STREAMED`` and ``GRPC`` body send modes. + // Instructs the data plane to stop sending body data and to send a + // half-close on the ext_proc stream. The ext_proc server should then echo + // back all subsequent body contents as-is until it sees the client's + // half-close, at which point the ext_proc server can terminate the stream + // with an OK status. This provides a safe way for the ext_proc server + // to indicate that it does not need to see the rest of the stream; + // without this, the ext_proc server could not terminate the stream + // early, because it would wind up dropping any body contents that the + // client had already sent before it saw the ext_proc stream termination. + bool request_drain = 11; + // When ext_proc server receives a request message, in case it needs more // time to process the message, it sends back a ProcessingResponse message // with a new timeout value. When the data plane receives this response From 8b95c5261759f0fe70d4103b6374a418d68ad619 Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Tue, 16 Sep 2025 08:05:35 -0700 Subject: [PATCH 20/26] Update api/envoy/extensions/filters/http/ext_proc/v3/processing_mode.proto Co-authored-by: Adi (Suissa) Peleg Signed-off-by: Mark D. Roth --- .../extensions/filters/http/ext_proc/v3/processing_mode.proto | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/envoy/extensions/filters/http/ext_proc/v3/processing_mode.proto b/api/envoy/extensions/filters/http/ext_proc/v3/processing_mode.proto index ccf84ddee3e8d..cc880f7042626 100644 --- a/api/envoy/extensions/filters/http/ext_proc/v3/processing_mode.proto +++ b/api/envoy/extensions/filters/http/ext_proc/v3/processing_mode.proto @@ -78,7 +78,7 @@ message ProcessingMode { // up to the buffer limit will be sent. BUFFERED_PARTIAL = 3; - // The ext_proc client streams the body to the server in pieces as they arrive. + // The ext_proc client (the data plane) streams the body to the server in pieces as they arrive. // // 1) The server may choose to buffer any number chunks of data before processing them. // After it finishes buffering, the server processes the buffered data. Then it splits the processed From 9186b12d86850c6af42ccbafccfee0a9ee14137c Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Tue, 16 Sep 2025 20:12:01 +0000 Subject: [PATCH 21/26] clarify wording Signed-off-by: Mark D. Roth --- .../extensions/filters/http/ext_proc/v3/processing_mode.proto | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/envoy/extensions/filters/http/ext_proc/v3/processing_mode.proto b/api/envoy/extensions/filters/http/ext_proc/v3/processing_mode.proto index cc880f7042626..5ad32af519f80 100644 --- a/api/envoy/extensions/filters/http/ext_proc/v3/processing_mode.proto +++ b/api/envoy/extensions/filters/http/ext_proc/v3/processing_mode.proto @@ -82,7 +82,7 @@ message ProcessingMode { // // 1) The server may choose to buffer any number chunks of data before processing them. // After it finishes buffering, the server processes the buffered data. Then it splits the processed - // data into any number of chunks, and streams them back to the client one by one. + // data into any number of chunks, and streams them back to the ext_proc client one by one. // The server may continuously do so until the complete body is processed. // The individual response chunk size is recommended to be no greater than 64K bytes, or // :ref:`max_receive_message_length ` From d2334a895e1c6ed1e79f7afffe22ba3051fb77e9 Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Tue, 16 Sep 2025 21:22:50 +0000 Subject: [PATCH 22/26] add end_of_stream_without_message field Signed-off-by: Mark D. Roth --- api/envoy/service/ext_proc/v3/external_processor.proto | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/api/envoy/service/ext_proc/v3/external_processor.proto b/api/envoy/service/ext_proc/v3/external_processor.proto index 96d3e2d1204ff..184e0db98b576 100644 --- a/api/envoy/service/ext_proc/v3/external_processor.proto +++ b/api/envoy/service/ext_proc/v3/external_processor.proto @@ -289,6 +289,14 @@ message HttpBody { // If ``true``, this will be the last ``HttpBody`` message that will be sent and no // trailers will be sent for the current request/response. bool end_of_stream = 2; + + // This field is used in ``GRPC`` body send mode when ``end_of_stream`` is + // true and ``body`` is empty. Those values would normally indicate an + // empty message on the stream with the end-of-stream bit set. + // However, if the half-close happens after the last message on the + // stream was already sent, then this field will be true to indicate an + // end-of-stream with *no* message (as opposed to an empty message). + bool end_of_stream_without_message = 3; } // This message is sent to the external server when the HTTP request and From ced8f28d38d01467b1a92bbb079b523bfefaf26f Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Tue, 16 Sep 2025 23:28:30 +0000 Subject: [PATCH 23/26] add end_of_stream_without_message in response also Signed-off-by: Mark D. Roth --- api/envoy/service/ext_proc/v3/external_processor.proto | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/api/envoy/service/ext_proc/v3/external_processor.proto b/api/envoy/service/ext_proc/v3/external_processor.proto index 184e0db98b576..ded5cfc3d9d82 100644 --- a/api/envoy/service/ext_proc/v3/external_processor.proto +++ b/api/envoy/service/ext_proc/v3/external_processor.proto @@ -456,6 +456,14 @@ message StreamedBodyResponse { // message, which will result in discarding any other messages sent by // the client application. bool end_of_stream = 2; + + // This field is used in ``GRPC`` body send mode when ``end_of_stream`` is + // true and ``body`` is empty. Those values would normally indicate an + // empty message on the stream with the end-of-stream bit set. + // However, if the half-close happens after the last message on the + // stream was already sent, then this field will be true to indicate an + // end-of-stream with *no* message (as opposed to an empty message). + bool end_of_stream_without_message = 3; } // This message specifies the body mutation the server sends to the data plane. From af6aa49b0766617af15775588effa792c3cddfc2 Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Thu, 2 Oct 2025 15:59:47 +0000 Subject: [PATCH 24/26] note that GRPC mode is similar to FULL_DUPLEX_STREAMED Signed-off-by: Mark D. Roth --- .../filters/http/ext_proc/v3/processing_mode.proto | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/api/envoy/extensions/filters/http/ext_proc/v3/processing_mode.proto b/api/envoy/extensions/filters/http/ext_proc/v3/processing_mode.proto index 726aa34d181e3..1744c3efb637f 100644 --- a/api/envoy/extensions/filters/http/ext_proc/v3/processing_mode.proto +++ b/api/envoy/extensions/filters/http/ext_proc/v3/processing_mode.proto @@ -110,10 +110,11 @@ message ProcessingMode { FULL_DUPLEX_STREAMED = 4; // [#not-implemented-hide:] - // gRPC traffic. In this mode, the ext_proc client will de-frame the - // individual gRPC messages inside the HTTP/2 DATA frames, and as each - // message is de-framed, it will be sent to the ext_proc server as a - // :ref:`request_body + // A mode for gRPC traffic. This is similar to ``FULL_DUPLEX_STREAMED``, + // except that instead of sending raw chunks of the HTTP/2 DATA frames, + // the ext_proc client will de-frame the individual gRPC messages inside + // the HTTP/2 DATA frames, and as each message is de-framed, it will be + // sent to the ext_proc server as a :ref:`request_body // ` // or :ref:`response_body // `. From ec538a395eaa3aa6d5bad17920b85e4e3ffac080 Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Thu, 2 Oct 2025 16:00:25 +0000 Subject: [PATCH 25/26] fix space Signed-off-by: Mark D. Roth --- .../extensions/filters/http/ext_proc/v3/processing_mode.proto | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/envoy/extensions/filters/http/ext_proc/v3/processing_mode.proto b/api/envoy/extensions/filters/http/ext_proc/v3/processing_mode.proto index 1744c3efb637f..dbe45d687872e 100644 --- a/api/envoy/extensions/filters/http/ext_proc/v3/processing_mode.proto +++ b/api/envoy/extensions/filters/http/ext_proc/v3/processing_mode.proto @@ -110,7 +110,7 @@ message ProcessingMode { FULL_DUPLEX_STREAMED = 4; // [#not-implemented-hide:] - // A mode for gRPC traffic. This is similar to ``FULL_DUPLEX_STREAMED``, + // A mode for gRPC traffic. This is similar to ``FULL_DUPLEX_STREAMED``, // except that instead of sending raw chunks of the HTTP/2 DATA frames, // the ext_proc client will de-frame the individual gRPC messages inside // the HTTP/2 DATA frames, and as each message is de-framed, it will be From 4fa776a4423c2dc2698452a44f58e201993e80ff Mon Sep 17 00:00:00 2001 From: "Mark D. Roth" Date: Tue, 7 Oct 2025 18:12:48 +0000 Subject: [PATCH 26/26] add a bit to indicate whether gRPC messages are compressed Signed-off-by: Mark D. Roth --- api/envoy/service/ext_proc/v3/external_processor.proto | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/api/envoy/service/ext_proc/v3/external_processor.proto b/api/envoy/service/ext_proc/v3/external_processor.proto index ded5cfc3d9d82..b2853d38e0762 100644 --- a/api/envoy/service/ext_proc/v3/external_processor.proto +++ b/api/envoy/service/ext_proc/v3/external_processor.proto @@ -297,6 +297,11 @@ message HttpBody { // stream was already sent, then this field will be true to indicate an // end-of-stream with *no* message (as opposed to an empty message). bool end_of_stream_without_message = 3; + + // This field is used in ``GRPC`` body send mode to indicate whether + // the message is compressed. This will never be set to true by gRPC + // but may be set to true by a proxy like Envoy. + bool grpc_message_compressed = 4; } // This message is sent to the external server when the HTTP request and @@ -464,6 +469,11 @@ message StreamedBodyResponse { // stream was already sent, then this field will be true to indicate an // end-of-stream with *no* message (as opposed to an empty message). bool end_of_stream_without_message = 3; + + // This field is used in ``GRPC`` body send mode to indicate whether + // the message is compressed. This will never be set to true by gRPC + // but may be set to true by a proxy like Envoy. + bool grpc_message_compressed = 4; } // This message specifies the body mutation the server sends to the data plane.