syntax = "proto3";

package envoy.api.v2;

option java_outer_classname = "SrdsProto";
option java_package = "io.envoyproxy.envoy.api.v2";
option java_multiple_files = true;
option java_generic_services = true;

import "envoy/api/v2/discovery.proto";

import "google/api/annotations.proto";

import "validate/validate.proto";
import "gogoproto/gogo.proto";

option (gogoproto.equal_all) = true;

// [#protodoc-title: HTTP scoped routing configuration]
// * Routing :ref:`architecture overview <arch_overview_http_routing>`
//
// .. attention::
//
//   The Scoped RDS API is not yet fully implemented and *should not* be enabled in
//   :ref:`envoy_api_msg_config.filter.network.http_connection_manager.v2.HttpConnectionManager`.
//
// TODO(AndresGuedez): Update :ref:`arch_overview_http_routing` with scoped routing overview and
// configuration details.

// The Scoped Routes Discovery Service (SRDS) API distributes
// :ref:`ScopedRouteConfiguration<envoy_api_msg.ScopedRouteConfiguration>` resources. Each
// ScopedRouteConfiguration resource represents a "routing scope" containing a mapping that allows
// the HTTP connection manager to dynamically assign a routing table (specified via
// a :ref:`RouteConfiguration<envoy_api_msg_RouteConfiguration>` message) to each HTTP request.
// [#proto-status: experimental]
service ScopedRoutesDiscoveryService {
  rpc StreamScopedRoutes(stream DiscoveryRequest) returns (stream DiscoveryResponse) {
  }

  rpc DeltaScopedRoutes(stream DeltaDiscoveryRequest) returns (stream DeltaDiscoveryResponse) {
  }

  rpc FetchScopedRoutes(DiscoveryRequest) returns (DiscoveryResponse) {
    option (google.api.http) = {
      post: "/v2/discovery:scoped-routes"
      body: "*"
    };
  }
}

// Specifies a routing scope, which associates a
// :ref:`Key<envoy_api_msg_ScopedRouteConfiguration.Key>` to a
// :ref:`envoy_api_msg_RouteConfiguration` (identified by its resource name).
//
// The HTTP connection manager builds up a table consisting of these Key to RouteConfiguration
// mappings, and looks up the RouteConfiguration to use per request according to the algorithm
// specified in the
// :ref:`scope_key_builder<envoy_api_field_config.filter.network.http_connection_manager.v2.ScopedRoutes.scope_key_builder>`
// assigned to the HttpConnectionManager.
//
// For example, with the following configurations (in YAML):
//
// HttpConnectionManager config:
//
// .. code::
//
//   ...
//   scoped_routes:
//     name: foo-scoped-routes
//     scope_key_builder:
//       fragments:
//         - header_value_extractor:
//             name: X-Route-Selector
//             element_separator: ,
//             element:
//               separator: =
//               key: vip
//
// ScopedRouteConfiguration resources (specified statically via
// :ref:`scoped_route_configurations_list<envoy_api_field_config.filter.network.http_connection_manager.v2.ScopedRoutes.scoped_route_configurations_list>`
// or obtained dynamically via SRDS):
//
// .. code::
//
//  (1)
//   name: route-scope1
//   route_configuration_name: route-config1
//   key:
//      fragments:
//        - string_key: 172.10.10.20
//
//  (2)
//   name: route-scope2
//   route_configuration_name: route-config2
//   key:
//     fragments:
//       - string_key: 172.20.20.30
//
// A request from a client such as:
//
// .. code::
//
//     GET / HTTP/1.1
//     Host: foo.com
//     X-Route-Selector: vip=172.10.10.20
//
// would result in the routing table defined by the `route-config1` RouteConfiguration being
// assigned to the HTTP request/stream.
//
// [#comment:next free field: 4]
// [#proto-status: experimental]
message ScopedRouteConfiguration {
  // The name assigned to the routing scope.
  string name = 1 [(validate.rules).string.min_bytes = 1];

  // Specifies a key which is matched against the output of the
  // :ref:`scope_key_builder<envoy_api_field_config.filter.network.http_connection_manager.v2.ScopedRoutes.scope_key_builder>`
  // specified in the HttpConnectionManager. The matching is done per HTTP request and is dependent
  // on the order of the fragments contained in the Key.
  message Key {
    message Fragment {
      oneof type {
        option (validate.required) = true;

        // A string to match against.
        string string_key = 1;
      }
    }

    // The ordered set of fragments to match against. The order must match the fragments in the
    // corresponding
    // :ref:`scope_key_builder<envoy_api_field_config.filter.network.http_connection_manager.v2.ScopedRoutes.scope_key_builder>`.
    repeated Fragment fragments = 1;
  }

  // The resource name to use for a :ref:`envoy_api_msg_DiscoveryRequest` to an RDS server to
  // fetch the :ref:`envoy_api_msg_RouteConfiguration` associated with this scope.
  string route_configuration_name = 2 [(validate.rules).string.min_bytes = 1];

  // The key to match against.
  Key key = 3 [(validate.rules).message.required = true];
}
