syntax = "proto3";

package envoy.extensions.filters.network.thrift_proxy.filters.header_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.header_to_metadata.v3";
option java_outer_classname = "HeaderToMetadataProto";
option java_multiple_files = true;
option go_package = "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/thrift_proxy/filters/header_to_metadata/v3;header_to_metadatav3";
option (udpa.annotations.file_status).package_version_status = ACTIVE;

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

message HeaderToMetadata {
  enum ValueType {
    STRING = 0;

    NUMBER = 1;

    // The value is a serialized `protobuf.Value
    // <https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/struct.proto#L62>`_.
    PROTOBUF_VALUE = 2;
  }

  // ValueEncode defines the encoding algorithm.
  enum ValueEncode {
    // The value is not encoded.
    NONE = 0;

    // The value is encoded in `Base64 <https://tools.ietf.org/html/rfc4648#section-4>`_.
    // Note: this is mostly used for STRING and PROTOBUF_VALUE to escape the
    // non-ASCII characters in the header.
    BASE64 = 1;
  }

  // [#next-free-field: 7]
  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 header value. If both are empty, the header 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 header 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}];

    // How is the value encoded, default is NONE (not encoded).
    // The value will be decoded accordingly before storing to metadata.
    ValueEncode encode = 6;
  }

  // A Rule defines what metadata to apply when a header is present or missing.
  message Rule {
    // Specifies that a match will be performed on the value of a header.
    //
    // The header to be extracted.
    string header = 1
        [(validate.rules).string = {min_len: 1 well_known_regex: HTTP_HEADER_NAME strict: false}];

    // If the header is present, apply this metadata KeyValuePair.
    //
    // If the value in the KeyValuePair is non-empty, it'll be used instead
    // of the header value.
    KeyValuePair on_present = 2;

    // If the header is not present, apply this metadata KeyValuePair.
    //
    // The value in the KeyValuePair must be set, since it'll be used in lieu
    // of the missing header value.
    KeyValuePair on_missing = 3;

    // Whether or not to remove the header after a rule is applied.
    //
    // This prevents headers from leaking.
    bool remove = 4;
  }

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