// Copyright 2023 Google LLC
//
// 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 google.cloud.networkservices.v1;

import "google/api/field_behavior.proto";
import "google/api/resource.proto";
import "google/protobuf/duration.proto";
import "google/protobuf/field_mask.proto";
import "google/protobuf/timestamp.proto";

option csharp_namespace = "Google.Cloud.NetworkServices.V1";
option go_package = "cloud.google.com/go/networkservices/apiv1/networkservicespb;networkservicespb";
option java_multiple_files = true;
option java_outer_classname = "HttpRouteProto";
option java_package = "com.google.cloud.networkservices.v1";
option php_namespace = "Google\\Cloud\\NetworkServices\\V1";
option ruby_package = "Google::Cloud::NetworkServices::V1";

// HttpRoute is the resource defining how HTTP traffic should be routed by a
// Mesh or Gateway resource.
message HttpRoute {
  option (google.api.resource) = {
    type: "networkservices.googleapis.com/HttpRoute"
    pattern: "projects/{project}/locations/{location}/httpRoutes/{http_route}"
  };

  // Specifies how to select a route rule based on HTTP request headers.
  message HeaderMatch {
    // Represents an integer value range.
    message IntegerRange {
      // Start of the range (inclusive)
      int32 start = 1;

      // End of the range (exclusive)
      int32 end = 2;
    }

    oneof MatchType {
      // The value of the header should match exactly the content of
      // exact_match.
      string exact_match = 2;

      // The value of the header must match the regular expression specified in
      // regex_match. For regular expression grammar, please see:
      // https://github.com/google/re2/wiki/Syntax
      string regex_match = 3;

      // The value of the header must start with the contents of prefix_match.
      string prefix_match = 4;

      // A header with header_name must exist. The match takes place whether or
      // not the header has a value.
      bool present_match = 5;

      // The value of the header must end with the contents of suffix_match.
      string suffix_match = 6;

      // If specified, the rule will match if the request header value is within
      // the range.
      IntegerRange range_match = 7;
    }

    // The name of the HTTP header to match against.
    string header = 1;

    // If specified, the match result will be inverted before checking. Default
    // value is set to false.
    bool invert_match = 8;
  }

  // Specifications to match a query parameter in the request.
  message QueryParameterMatch {
    oneof MatchType {
      // The value of the query parameter must exactly match the contents of
      // exact_match.
      //
      // Only one of exact_match, regex_match, or present_match must be set.
      string exact_match = 2;

      // The value of the query parameter must match the regular expression
      // specified by regex_match. For regular expression grammar, please see
      // https://github.com/google/re2/wiki/Syntax
      //
      // Only one of exact_match, regex_match, or present_match must be set.
      string regex_match = 3;

      // Specifies that the QueryParameterMatcher matches if request contains
      // query parameter, irrespective of whether the parameter has a value or
      // not.
      //
      // Only one of exact_match, regex_match, or present_match must be set.
      bool present_match = 4;
    }

    // The name of the query parameter to match.
    string query_parameter = 1;
  }

  // RouteMatch defines specifications used to match requests. If multiple match
  // types are set, this RouteMatch will match if ALL type of matches are
  // matched.
  message RouteMatch {
    oneof PathMatch {
      // The HTTP request path value should exactly match this value.
      //
      // Only one of full_path_match, prefix_match, or regex_match should be
      // used.
      string full_path_match = 1;

      // The HTTP request path value must begin with specified prefix_match.
      // prefix_match must begin with a /.
      //
      // Only one of full_path_match, prefix_match, or regex_match should be
      // used.
      string prefix_match = 2;

      // The HTTP request path value must satisfy the regular expression
      // specified by regex_match after removing any query parameters and anchor
      // supplied with the original URL. For regular expression grammar, please
      // see https://github.com/google/re2/wiki/Syntax
      //
      // Only one of full_path_match, prefix_match, or regex_match should be
      // used.
      string regex_match = 3;
    }

    // Specifies if prefix_match and full_path_match matches are case sensitive.
    // The default value is false.
    bool ignore_case = 4;

    // Specifies a list of HTTP request headers to match against. ALL of the
    // supplied headers must be matched.
    repeated HeaderMatch headers = 5;

    // Specifies a list of query parameters to match against. ALL of the query
    // parameters must be matched.
    repeated QueryParameterMatch query_parameters = 6;
  }

  // Specifications of a destination to which the request should be routed to.
  message Destination {
    // The URL of a BackendService to route traffic to.
    string service_name = 1 [(google.api.resource_reference) = {
      type: "compute.googleapis.com/BackendService"
    }];

    // Specifies the proportion of requests forwarded to the backend referenced
    // by the serviceName field. This is computed as:
    // - weight/Sum(weights in this destination list).
    // For non-zero values, there may be some epsilon from the exact proportion
    // defined here depending on the precision an implementation supports.
    //
    // If only one serviceName is specified and it has a weight greater than 0,
    // 100% of the traffic is forwarded to that backend.
    //
    // If weights are specified for any one service name, they need to be
    // specified for all of them.
    //
    // If weights are unspecified for all services, then, traffic is distributed
    // in equal proportions to all of them.
    int32 weight = 2;
  }

  // The specification for redirecting traffic.
  message Redirect {
    // Supported HTTP response code.
    enum ResponseCode {
      // Default value
      RESPONSE_CODE_UNSPECIFIED = 0;

      // Corresponds to 301.
      MOVED_PERMANENTLY_DEFAULT = 1;

      // Corresponds to 302.
      FOUND = 2;

      // Corresponds to 303.
      SEE_OTHER = 3;

      // Corresponds to 307. In this case, the request method will be retained.
      TEMPORARY_REDIRECT = 4;

      // Corresponds to 308. In this case, the request method will be retained.
      PERMANENT_REDIRECT = 5;
    }

    // The host that will be used in the redirect response instead of the one
    // that was supplied in the request.
    string host_redirect = 1;

    // The path that will be used in the redirect response instead of the one
    // that was supplied in the request.
    // path_redirect can not be supplied together with prefix_redirect. Supply
    // one alone or neither. If neither is supplied, the path of the original
    // request will be used for the redirect.
    string path_redirect = 2;

    // Indicates that during redirection, the matched prefix (or path) should be
    // swapped with this value. This option allows URLs be dynamically created
    // based on the request.
    string prefix_rewrite = 3;

    // The HTTP Status code to use for the redirect.
    ResponseCode response_code = 4;

    // If set to true, the URL scheme in the redirected request is set to https.
    // If set to false, the URL scheme of the redirected request will remain the
    // same as that of the request.
    //
    // The default is set to false.
    bool https_redirect = 5;

    // if set to true, any accompanying query portion of the original URL is
    // removed prior to redirecting the request. If set to false, the query
    // portion of the original URL is retained.
    //
    // The default is set to false.
    bool strip_query = 6;

    // The port that will be used in the redirected request instead of the one
    // that was supplied in the request.
    int32 port_redirect = 7;
  }

  // The specification for fault injection introduced into traffic to test the
  // resiliency of clients to destination service failure. As part of fault
  // injection, when clients send requests to a destination, delays can be
  // introduced by client proxy on a percentage of requests before sending those
  // requests to the destination service. Similarly requests can be aborted by
  // client proxy for a percentage of requests.
  message FaultInjectionPolicy {
    // Specification of how client requests are delayed as part of fault
    // injection before being sent to a destination.
    message Delay {
      // Specify a fixed delay before forwarding the request.
      google.protobuf.Duration fixed_delay = 1;

      // The percentage of traffic on which delay will be injected.
      //
      // The value must be between [0, 100]
      int32 percentage = 2;
    }

    // Specification of how client requests are aborted as part of fault
    // injection before being sent to a destination.
    message Abort {
      // The HTTP status code used to abort the request.
      //
      // The value must be between 200 and 599 inclusive.
      int32 http_status = 1;

      // The percentage of traffic which will be aborted.
      //
      // The value must be between [0, 100]
      int32 percentage = 2;
    }

    // The specification for injecting delay to client requests.
    Delay delay = 1;

    // The specification for aborting to client requests.
    Abort abort = 2;
  }

  // The specification for modifying HTTP header in HTTP request and HTTP
  // response.
  message HeaderModifier {
    // Completely overwrite/replace the headers with given map where key is the
    // name of the header, value is the value of the header.
    map<string, string> set = 1;

    // Add the headers with given map where key is the name of the header, value
    // is the value of the header.
    map<string, string> add = 2;

    // Remove headers (matching by header names) specified in the list.
    repeated string remove = 3;
  }

  // The specification for modifying the URL of the request, prior to forwarding
  // the request to the destination.
  message URLRewrite {
    // Prior to forwarding the request to the selected destination, the matching
    // portion of the requests path is replaced by this value.
    string path_prefix_rewrite = 1;

    // Prior to forwarding the request to the selected destination, the requests
    // host header is replaced by this value.
    string host_rewrite = 2;
  }

  // The specifications for retries.
  message RetryPolicy {
    // Specifies one or more conditions when this retry policy applies. Valid
    // values are:
    //   5xx: Proxy will attempt a retry if the destination service responds
    //     with any 5xx response code, of if the destination service does not
    //     respond at all, example: disconnect, reset, read timeout, connection
    //     failure and refused streams.
    //
    //   gateway-error: Similar to 5xx, but only applies to response codes 502,
    //     503, 504.
    //
    //   reset: Proxy will attempt a retry if the destination service does not
    //     respond at all (disconnect/reset/read timeout)
    //
    //   connect-failure: Proxy will retry on failures connecting to destination
    //     for example due to connection timeouts.
    //
    //   retriable-4xx: Proxy will retry fro retriable 4xx response codes.
    //     Currently the only retriable error supported is 409.
    //
    //   refused-stream: Proxy will retry if the destination resets the stream
    //     with a REFUSED_STREAM error code. This reset type indicates that it
    //     is safe to retry.
    repeated string retry_conditions = 1;

    // Specifies the allowed number of retries. This number must be > 0. If not
    // specified, default to 1.
    int32 num_retries = 2;

    // Specifies a non-zero timeout per retry attempt.
    google.protobuf.Duration per_try_timeout = 3;
  }

  // Specifies the policy on how requests are shadowed to a separate mirrored
  // destination service. The proxy does not wait for responses from the
  // shadow service. Prior to sending traffic to the shadow service, the
  // host/authority header is suffixed with -shadow.
  message RequestMirrorPolicy {
    // The destination the requests will be mirrored to. The weight of the
    // destination will be ignored.
    Destination destination = 1;
  }

  // The Specification for allowing client side cross-origin requests.
  message CorsPolicy {
    // Specifies the list of origins that will be allowed to do CORS requests.
    // An origin is allowed if it matches either an item in allow_origins or
    // an item in allow_origin_regexes.
    repeated string allow_origins = 1;

    // Specifies the regular expression patterns that match allowed origins. For
    // regular expression grammar, please see
    // https://github.com/google/re2/wiki/Syntax.
    repeated string allow_origin_regexes = 2;

    // Specifies the content for Access-Control-Allow-Methods header.
    repeated string allow_methods = 3;

    // Specifies the content for Access-Control-Allow-Headers header.
    repeated string allow_headers = 4;

    // Specifies the content for Access-Control-Expose-Headers header.
    repeated string expose_headers = 5;

    // Specifies how long result of a preflight request can be cached in
    // seconds. This translates to the Access-Control-Max-Age header.
    string max_age = 6;

    // In response to a preflight request, setting this to true indicates that
    // the actual request can include user credentials. This translates to the
    // Access-Control-Allow-Credentials header.
    //
    // Default value is false.
    bool allow_credentials = 7;

    // If true, the CORS policy is disabled. The default value is false, which
    // indicates that the CORS policy is in effect.
    bool disabled = 8;
  }

  // The specifications for routing traffic and applying associated policies.
  message RouteAction {
    // The destination to which traffic should be forwarded.
    repeated Destination destinations = 1;

    // If set, the request is directed as configured by this field.
    Redirect redirect = 2;

    // The specification for fault injection introduced into traffic to test the
    // resiliency of clients to backend service failure. As part of fault
    // injection, when clients send requests to a backend service, delays can be
    // introduced  on a percentage of requests before sending those requests to
    // the backend service. Similarly requests from clients can be aborted for a
    // percentage of requests.
    //
    // timeout and retry_policy will be ignored by clients that are configured
    // with a fault_injection_policy
    FaultInjectionPolicy fault_injection_policy = 4;

    // The specification for modifying the headers of a matching request prior
    // to delivery of the request to the destination. If HeaderModifiers are set
    // on both the Destination and the RouteAction, they will be merged.
    // Conflicts between the two will not be resolved on the configuration.
    HeaderModifier request_header_modifier = 5;

    // The specification for modifying the headers of a response prior to
    // sending the response back to the client. If HeaderModifiers are set
    // on both the Destination and the RouteAction, they will be merged.
    // Conflicts between the two will not be resolved on the configuration.
    HeaderModifier response_header_modifier = 6;

    // The specification for rewrite URL before forwarding requests to the
    // destination.
    URLRewrite url_rewrite = 7;

    // Specifies the timeout for selected route. Timeout is computed from the
    // time the request has been fully processed (i.e. end of stream) up until
    // the response has been completely processed. Timeout includes all retries.
    google.protobuf.Duration timeout = 8;

    // Specifies the retry policy associated with this route.
    RetryPolicy retry_policy = 9;

    // Specifies the policy on how requests intended for the routes destination
    // are shadowed to a separate mirrored destination. Proxy will not wait for
    // the shadow destination to respond before returning the response. Prior to
    // sending traffic to the shadow service, the host/authority header is
    // suffixed with -shadow.
    RequestMirrorPolicy request_mirror_policy = 10;

    // The specification for allowing client side cross-origin requests.
    CorsPolicy cors_policy = 11;
  }

  // Specifies how to match traffic and how to route traffic when traffic is
  // matched.
  message RouteRule {
    // A list of matches define conditions used for matching the rule against
    // incoming HTTP requests. Each match is independent, i.e. this rule will be
    // matched if ANY one of the matches is satisfied.
    //
    // If no matches field is specified, this rule will unconditionally match
    // traffic.
    //
    // If a default rule is desired to be configured, add a rule with no matches
    // specified to the end of the rules list.
    repeated RouteMatch matches = 1;

    // The detailed rule defining how to route matched traffic.
    RouteAction action = 2;
  }

  // Required. Name of the HttpRoute resource. It matches pattern
  // `projects/*/locations/global/httpRoutes/http_route_name>`.
  string name = 1 [(google.api.field_behavior) = REQUIRED];

  // Output only. Server-defined URL of this resource
  string self_link = 11 [(google.api.field_behavior) = OUTPUT_ONLY];

  // Optional. A free-text description of the resource. Max length 1024
  // characters.
  string description = 2 [(google.api.field_behavior) = OPTIONAL];

  // Output only. The timestamp when the resource was created.
  google.protobuf.Timestamp create_time = 3
      [(google.api.field_behavior) = OUTPUT_ONLY];

  // Output only. The timestamp when the resource was updated.
  google.protobuf.Timestamp update_time = 4
      [(google.api.field_behavior) = OUTPUT_ONLY];

  // Required. Hostnames define a set of hosts that should match against the
  // HTTP host header to select a HttpRoute to process the request. Hostname is
  // the fully qualified domain name of a network host, as defined by RFC 1123
  // with the exception that:
  //  - IPs are not allowed.
  //  - A hostname may be prefixed with a wildcard label (`*.`). The wildcard
  //    label must appear by itself as the first label.
  //
  // Hostname can be "precise" which is a domain name without the terminating
  // dot of a network host (e.g. `foo.example.com`) or "wildcard", which is a
  // domain name prefixed with a single wildcard label (e.g. `*.example.com`).
  //
  // Note that as per RFC1035 and RFC1123, a label must consist of lower case
  // alphanumeric characters or '-', and must start and end with an alphanumeric
  // character. No other punctuation is allowed.
  //
  // The routes associated with a Mesh or Gateways  must have unique hostnames.
  // If you attempt to attach multiple routes with conflicting hostnames,
  // the configuration will be rejected.
  //
  // For example, while it is acceptable for routes for the hostnames
  // `*.foo.bar.com` and `*.bar.com` to be associated with the same Mesh (or
  // Gateways under the same scope), it is not possible to associate two routes
  // both with `*.bar.com` or both with `bar.com`.
  repeated string hostnames = 5 [(google.api.field_behavior) = REQUIRED];

  // Optional. Meshes defines a list of meshes this HttpRoute is attached to, as
  // one of the routing rules to route the requests served by the mesh.
  //
  // Each mesh reference should match the pattern:
  // `projects/*/locations/global/meshes/<mesh_name>`
  //
  // The attached Mesh should be of a type SIDECAR
  repeated string meshes = 8 [
    (google.api.field_behavior) = OPTIONAL,
    (google.api.resource_reference) = {
      type: "networkservices.googleapis.com/Mesh"
    }
  ];

  // Optional. Gateways defines a list of gateways this HttpRoute is attached
  // to, as one of the routing rules to route the requests served by the
  // gateway.
  //
  // Each gateway reference should match the pattern:
  // `projects/*/locations/global/gateways/<gateway_name>`
  repeated string gateways = 9 [
    (google.api.field_behavior) = OPTIONAL,
    (google.api.resource_reference) = {
      type: "networkservices.googleapis.com/Gateway"
    }
  ];

  // Optional. Set of label tags associated with the HttpRoute resource.
  map<string, string> labels = 10 [(google.api.field_behavior) = OPTIONAL];

  // Required. Rules that define how traffic is routed and handled.
  // Rules will be matched sequentially based on the RouteMatch specified for
  // the rule.
  repeated RouteRule rules = 6 [(google.api.field_behavior) = REQUIRED];
}

// Request used with the ListHttpRoutes method.
message ListHttpRoutesRequest {
  // Required. The project and location from which the HttpRoutes should be
  // listed, specified in the format `projects/*/locations/global`.
  string parent = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      child_type: "networkservices.googleapis.com/HttpRoute"
    }
  ];

  // Maximum number of HttpRoutes to return per call.
  int32 page_size = 2;

  // The value returned by the last `ListHttpRoutesResponse`
  // Indicates that this is a continuation of a prior `ListHttpRoutes` call,
  // and that the system should return the next page of data.
  string page_token = 3;
}

// Response returned by the ListHttpRoutes method.
message ListHttpRoutesResponse {
  // List of HttpRoute resources.
  repeated HttpRoute http_routes = 1;

  // If there might be more results than those appearing in this response, then
  // `next_page_token` is included. To get the next set of results, call this
  // method again using the value of `next_page_token` as `page_token`.
  string next_page_token = 2;
}

// Request used by the GetHttpRoute method.
message GetHttpRouteRequest {
  // Required. A name of the HttpRoute to get. Must be in the format
  // `projects/*/locations/global/httpRoutes/*`.
  string name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "networkservices.googleapis.com/HttpRoute"
    }
  ];
}

// Request used by the HttpRoute method.
message CreateHttpRouteRequest {
  // Required. The parent resource of the HttpRoute. Must be in the
  // format `projects/*/locations/global`.
  string parent = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      child_type: "networkservices.googleapis.com/HttpRoute"
    }
  ];

  // Required. Short name of the HttpRoute resource to be created.
  string http_route_id = 2 [(google.api.field_behavior) = REQUIRED];

  // Required. HttpRoute resource to be created.
  HttpRoute http_route = 3 [(google.api.field_behavior) = REQUIRED];
}

// Request used by the UpdateHttpRoute method.
message UpdateHttpRouteRequest {
  // Optional. Field mask is used to specify the fields to be overwritten in the
  // HttpRoute resource by the update.
  // The fields specified in the update_mask are relative to the resource, not
  // the full request. A field will be overwritten if it is in the mask. If the
  // user does not provide a mask then all fields will be overwritten.
  google.protobuf.FieldMask update_mask = 1
      [(google.api.field_behavior) = OPTIONAL];

  // Required. Updated HttpRoute resource.
  HttpRoute http_route = 2 [(google.api.field_behavior) = REQUIRED];
}

// Request used by the DeleteHttpRoute method.
message DeleteHttpRouteRequest {
  // Required. A name of the HttpRoute to delete. Must be in the format
  // `projects/*/locations/global/httpRoutes/*`.
  string name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "networkservices.googleapis.com/HttpRoute"
    }
  ];
}
