syntax = "proto3";

package envoy.extensions.filters.network.thrift_proxy.filters.payload_to_metadata.v3;

import "envoy/type/matcher/v3/regex.proto";

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

option java_package = "io.envoyproxy.envoy.extensions.filters.network.thrift_proxy.filters.payload_to_metadata.v3";
option java_outer_classname = "PayloadToMetadataProto";
option java_multiple_files = true;
option go_package = "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/thrift_proxy/filters/payload_to_metadata/v3;payload_to_metadatav3";
option (udpa.annotations.file_status).package_version_status = ACTIVE;

// [#protodoc-title: Payload-To-Metadata Filter]
//
// The configuration for transforming payloads into metadata. This is useful
// for matching load balancer subsets, logging, etc.
//
// Payload to Metadata :ref:`configuration overview <config_thrift_filters_payload_to_metadata>`.
// [#extension: envoy.filters.thrift.payload_to_metadata]

message PayloadToMetadata {
  enum ValueType {
    STRING = 0;
    NUMBER = 1;
  }

  // [#next-free-field: 6]
  message KeyValuePair {
    // The namespace — if this is empty, the filter's namespace will be used.
    string metadata_namespace = 1;

    // The key to use within the namespace.
    string key = 2 [(validate.rules).string = {min_len: 1}];

    oneof value_type {
      // The value to pair with the given key.
      //
      // When used for on_present case, if value is non-empty it'll be used instead
      // of the field value. If both are empty, the field value is used as-is.
      //
      // When used for on_missing case, a non-empty value must be provided.
      string value = 3;

      // If present, the header's value will be matched and substituted with this.
      // If there is no match or substitution, the field value is used as-is.
      //
      // This is only used for on_present.
      type.matcher.v3.RegexMatchAndSubstitute regex_value_rewrite = 4;
    }

    // The value's type — defaults to string.
    ValueType type = 5 [(validate.rules).enum = {defined_only: true}];
  }

  // A Rule defines what metadata to apply when a field is present or missing.
  // [#next-free-field: 6]
  message Rule {
    oneof match_specifier {
      option (validate.required) = true;

      // If specified, the route must exactly match the request method name. As a special case,
      // an empty string matches any request method name.
      string method_name = 1;

      // If specified, the route must have the service name as the request method name prefix.
      // As a special case, an empty string matches any service name. Only relevant when service
      // multiplexing.
      string service_name = 2;
    }

    // Specifies that a match will be performed on the value of a field.
    FieldSelector field_selector = 3 [(validate.rules).message = {required: true}];

    // If the field is present, apply this metadata KeyValuePair.
    KeyValuePair on_present = 4;

    // If the field is missing, apply this metadata KeyValuePair.
    //
    // The value in the KeyValuePair must be set, since it'll be used in lieu
    // of the missing field value.
    KeyValuePair on_missing = 5;
  }

  message FieldSelector {
    // field name to log
    string name = 1 [(validate.rules).string = {min_len: 1}];

    // field id to match
    int32 id = 2 [(validate.rules).int32 = {lte: 32767 gte: -32768}];

    // next node of the field selector
    FieldSelector child = 3;
  }

  // The list of rules to apply to requests.
  repeated Rule request_rules = 1 [(validate.rules).repeated = {min_items: 1}];
}
