// Copyright 2025 Envoy Project Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// 
//     http://www.apache.org/licenses/LICENSE-2.0
// 
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

syntax = "proto3";

package envoy.extensions.filters.http.ext_proc.v3;

import "udpa/annotations/status.proto";
import "validate/validate.proto";

option java_package = "io.envoyproxy.envoy.extensions.filters.http.ext_proc.v3";
option java_outer_classname = "ProcessingModeProto";
option java_multiple_files = true;
option go_package = "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/ext_proc/v3;ext_procv3";
option (udpa.annotations.file_status).package_version_status = ACTIVE;

// [#protodoc-title: External Processing Filter]
// External Processing Filter Processing Mode
// [#extension: envoy.filters.http.ext_proc]

// This configuration describes which parts of an HTTP request and
// response are sent to a remote server and how they are delivered.

// [#next-free-field: 7]
message ProcessingMode {
  // Control how headers and trailers are handled
  enum HeaderSendMode {
    // When used to configure the ext_proc filter :ref:`processing_mode
    // <envoy_v3_api_field_extensions.filters.http.ext_proc.v3.ExternalProcessor.processing_mode>`,
    // the default HeaderSendMode depends on which part of the message is being processed. By
    // default, request and response headers are sent, while trailers are skipped.
    //
    // When used in :ref:`mode_override
    // <envoy_v3_api_field_service.ext_proc.v3.ProcessingResponse.mode_override>` or
    // :ref:`allowed_override_modes
    // <envoy_v3_api_field_extensions.filters.http.ext_proc.v3.ExternalProcessor.allowed_override_modes>`,
    // a value of DEFAULT indicates that there is no change from the behavior that is configured for
    // the filter in :ref:`processing_mode
    // <envoy_v3_api_field_extensions.filters.http.ext_proc.v3.ExternalProcessor.processing_mode>`.
    DEFAULT = 0;

    // Send the header or trailer.
    SEND = 1;

    // Do not send the header or trailer.
    SKIP = 2;
  }

  // Control how the request and response bodies are handled
  // When body mutation by external processor is enabled, ext_proc filter will always remove
  // the content length header in four cases below because content length can not be guaranteed
  // to be set correctly:
  // 1) STREAMED BodySendMode: header processing completes before body mutation comes back.
  // 2) BUFFERED_PARTIAL BodySendMode: body is buffered and could be injected in different phases.
  // 3) BUFFERED BodySendMode + SKIP HeaderSendMode: header processing (e.g., update content-length) is skipped.
  // 4) FULL_DUPLEX_STREAMED BodySendMode: header processing completes before body mutation comes back.
  //
  // In Envoy's http1 codec implementation, removing content length will enable chunked transfer
  // encoding whenever feasible. The recipient (either client or server) must be able
  // to parse and decode the chunked transfer coding.
  // (see `details in RFC9112 <https://tools.ietf.org/html/rfc9112#section-7.1>`_).
  //
  // In BUFFERED BodySendMode + SEND HeaderSendMode, content length header is allowed but it is
  // external processor's responsibility to set the content length correctly matched to the length
  // of mutated body. If they don't match, the corresponding body mutation will be rejected and
  // local reply will be sent with an error message.
  enum BodySendMode {
    // 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.
    STREAMED = 1;

    // 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.
    BUFFERED = 2;

    // 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.
    BUFFERED_PARTIAL = 3;

    // Envoy 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.
    // 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 <envoy_v3_api_field_config.core.v3.GrpcService.EnvoyGrpc.max_receive_message_length>`
    // if EnvoyGrpc is used.
    //
    // 2) The server may also choose to buffer the entire message, including the headers (if header mode is
    // ``SEND``), the entire body, and the trailers (if present), before sending back any response.
    // The server response has to maintain the headers-body-trailers ordering.
    //
    // 3) Note that the server might also choose not to buffer data. That is, upon receiving a
    // body request, it could process the data and send back a body response immediately.
    //
    // 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.
    //   Sending the trailers (if present) is to inform the server the complete body arrives.
    //   In case there are no trailers, then Envoy will set
    //   :ref:`end_of_stream <envoy_v3_api_field_service.ext_proc.v3.HttpBody.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 <envoy_v3_api_msg_service.ext_proc.v3.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.

    FULL_DUPLEX_STREAMED = 4;
  }

  // How to handle the request header. Default is "SEND".
  // Note this field is ignored in :ref:`mode_override
  // <envoy_v3_api_field_service.ext_proc.v3.ProcessingResponse.mode_override>`, since mode
  // overrides can only affect messages exchanged after the request header is processed.
  HeaderSendMode request_header_mode = 1 [(validate.rules).enum = {defined_only: true}];

  // How to handle the response header. Default is "SEND".
  HeaderSendMode response_header_mode = 2 [(validate.rules).enum = {defined_only: true}];

  // How to handle the request body. Default is "NONE".
  BodySendMode request_body_mode = 3 [(validate.rules).enum = {defined_only: true}];

  // How do handle the response body. Default is "NONE".
  BodySendMode response_body_mode = 4 [(validate.rules).enum = {defined_only: true}];

  // How to handle the request trailers. Default is "SKIP".
  HeaderSendMode request_trailer_mode = 5 [(validate.rules).enum = {defined_only: true}];

  // How to handle the response trailers. Default is "SKIP".
  HeaderSendMode response_trailer_mode = 6 [(validate.rules).enum = {defined_only: true}];
}
