diff --git a/kubernetes/customresourcedefinitions.gen.yaml b/kubernetes/customresourcedefinitions.gen.yaml index 7318e07ffd..08e49dde23 100644 --- a/kubernetes/customresourcedefinitions.gen.yaml +++ b/kubernetes/customresourcedefinitions.gen.yaml @@ -11523,19 +11523,31 @@ spec: description: The name assigned to the route for debugging purposes. type: string redirect: + allOf: + - oneOf: + - not: + anyOf: + - required: + - port + - required: + - derivePort + - required: + - port + - required: + - derivePort + - oneOf: + - not: + anyOf: + - required: + - prefixRewrite + - required: + - uriRegexRewrite + - required: + - prefixRewrite + - required: + - uriRegexRewrite description: A HTTP rule can either return a direct_response, redirect or forward (default) traffic. - oneOf: - - not: - anyOf: - - required: - - port - - required: - - derivePort - - required: - - port - - required: - - derivePort properties: authority: description: On a redirect, overwrite the Authority/Host @@ -11556,6 +11568,10 @@ spec: maximum: 4294967295 minimum: 0 type: integer + prefixRewrite: + description: On a redirect, replace the matched prefix (or + the entire path for exact matches) with this value. + type: string redirectCode: description: On a redirect, Specifies the HTTP status code to use in the redirect response. @@ -11570,6 +11586,18 @@ spec: description: On a redirect, overwrite the Path portion of the URL with this value. type: string + uriRegexRewrite: + description: On a redirect, rewrite the path portion of + the URI with the specified RE2 regex. + properties: + match: + description: '[RE2 style regex-based match](https://github.com/google/re2/wiki/Syntax).' + type: string + rewrite: + description: The string that should replace into matching + portions of original URI. + type: string + type: object type: object retries: description: Retry policy for HTTP requests. @@ -12575,19 +12603,31 @@ spec: description: The name assigned to the route for debugging purposes. type: string redirect: + allOf: + - oneOf: + - not: + anyOf: + - required: + - port + - required: + - derivePort + - required: + - port + - required: + - derivePort + - oneOf: + - not: + anyOf: + - required: + - prefixRewrite + - required: + - uriRegexRewrite + - required: + - prefixRewrite + - required: + - uriRegexRewrite description: A HTTP rule can either return a direct_response, redirect or forward (default) traffic. - oneOf: - - not: - anyOf: - - required: - - port - - required: - - derivePort - - required: - - port - - required: - - derivePort properties: authority: description: On a redirect, overwrite the Authority/Host @@ -12608,6 +12648,10 @@ spec: maximum: 4294967295 minimum: 0 type: integer + prefixRewrite: + description: On a redirect, replace the matched prefix (or + the entire path for exact matches) with this value. + type: string redirectCode: description: On a redirect, Specifies the HTTP status code to use in the redirect response. @@ -12622,6 +12666,18 @@ spec: description: On a redirect, overwrite the Path portion of the URL with this value. type: string + uriRegexRewrite: + description: On a redirect, rewrite the path portion of + the URI with the specified RE2 regex. + properties: + match: + description: '[RE2 style regex-based match](https://github.com/google/re2/wiki/Syntax).' + type: string + rewrite: + description: The string that should replace into matching + portions of original URI. + type: string + type: object type: object retries: description: Retry policy for HTTP requests. @@ -13627,19 +13683,31 @@ spec: description: The name assigned to the route for debugging purposes. type: string redirect: + allOf: + - oneOf: + - not: + anyOf: + - required: + - port + - required: + - derivePort + - required: + - port + - required: + - derivePort + - oneOf: + - not: + anyOf: + - required: + - prefixRewrite + - required: + - uriRegexRewrite + - required: + - prefixRewrite + - required: + - uriRegexRewrite description: A HTTP rule can either return a direct_response, redirect or forward (default) traffic. - oneOf: - - not: - anyOf: - - required: - - port - - required: - - derivePort - - required: - - port - - required: - - derivePort properties: authority: description: On a redirect, overwrite the Authority/Host @@ -13660,6 +13728,10 @@ spec: maximum: 4294967295 minimum: 0 type: integer + prefixRewrite: + description: On a redirect, replace the matched prefix (or + the entire path for exact matches) with this value. + type: string redirectCode: description: On a redirect, Specifies the HTTP status code to use in the redirect response. @@ -13674,6 +13746,18 @@ spec: description: On a redirect, overwrite the Path portion of the URL with this value. type: string + uriRegexRewrite: + description: On a redirect, rewrite the path portion of + the URI with the specified RE2 regex. + properties: + match: + description: '[RE2 style regex-based match](https://github.com/google/re2/wiki/Syntax).' + type: string + rewrite: + description: The string that should replace into matching + portions of original URI. + type: string + type: object type: object retries: description: Retry policy for HTTP requests. diff --git a/networking/v1/virtual_service_alias.gen.go b/networking/v1/virtual_service_alias.gen.go index 2ce6d25923..0151ff8ec6 100644 --- a/networking/v1/virtual_service_alias.gen.go +++ b/networking/v1/virtual_service_alias.gen.go @@ -520,6 +520,33 @@ type TLSMatchAttributes = v1alpha3.TLSMatchAttributes // ... // // ``` +// +// The following rule redirects requests with a path prefix of /foo to the +// authority foo.example.com, stripping the /foo prefix from the path: +// +// ```yaml +// apiVersion: networking.istio.io/v1 +// kind: VirtualService +// metadata: +// +// name: foo-redirect +// +// spec: +// +// hosts: +// - example.com +// http: +// - match: +// - uri: +// prefix: /foo/ +// redirect: +// authority: foo.example.com +// prefix_rewrite: / +// +// ``` +// +// With this rule, a request to example.com/foo/bar is redirected to +// foo.example.com/bar. type HTTPRedirect = v1alpha3.HTTPRedirect type HTTPRedirect_RedirectPortSelection = v1alpha3.HTTPRedirect_RedirectPortSelection @@ -534,6 +561,26 @@ type HTTPRedirect_Port = v1alpha3.HTTPRedirect_Port // * FROM_REQUEST_PORT: automatically use the port of the request. type HTTPRedirect_DerivePort = v1alpha3.HTTPRedirect_DerivePort +// On a redirect, replace the matched prefix (or the entire path for exact +// matches) with this value. The route match must use a prefix match type. +// The matched prefix is stripped from the path and this value is prepended. +// +// Examples (route prefix match: /foo): +// - prefix_rewrite: /bar → /foo/baz becomes /bar/baz +// - prefix_rewrite: / → /foo/baz becomes //baz (use /foo/ match to get /baz) +// +// Mutually exclusive with uri and uri_regex_rewrite. +type HTTPRedirect_PrefixRewrite = v1alpha3.HTTPRedirect_PrefixRewrite + +// On a redirect, rewrite the path portion of the URI with the specified +// RE2 regex. Capture groups in the pattern may be referenced in the +// replacement string. +// +// Example: match "^/foo(/.*)$" with rewrite "\\1" rewrites /foo/bar to /bar. +// +// Mutually exclusive with uri and prefix_rewrite. +type HTTPRedirect_UriRegexRewrite = v1alpha3.HTTPRedirect_UriRegexRewrite + // HTTPDirectResponse can be used to send a fixed response to clients. // For example, the following rule returns a fixed 503 status with a body // to requests for /v1/getProductRatings API. diff --git a/networking/v1alpha3/virtual_service.pb.go b/networking/v1alpha3/virtual_service.pb.go index d4db2ab0c6..07480888e2 100644 --- a/networking/v1alpha3/virtual_service.pb.go +++ b/networking/v1alpha3/virtual_service.pb.go @@ -2021,11 +2021,40 @@ func (x *TLSMatchAttributes) GetSourceNamespace() string { // ... // // ``` +// +// The following rule redirects requests with a path prefix of /foo to the +// authority foo.example.com, stripping the /foo prefix from the path: +// +// ```yaml +// apiVersion: networking.istio.io/v1 +// kind: VirtualService +// metadata: +// +// name: foo-redirect +// +// spec: +// +// hosts: +// - example.com +// http: +// - match: +// - uri: +// prefix: /foo/ +// redirect: +// authority: foo.example.com +// prefix_rewrite: / +// +// ``` +// +// With this rule, a request to example.com/foo/bar is redirected to +// foo.example.com/bar. type HTTPRedirect struct { state protoimpl.MessageState `protogen:"open.v1"` // On a redirect, overwrite the Path portion of the URL with this // value. Note that the entire path will be replaced, irrespective of the // request URI being matched as an exact path or prefix. + // + // Mutually exclusive with prefix_rewrite and uri_regex_rewrite. Uri string `protobuf:"bytes,1,opt,name=uri,proto3" json:"uri,omitempty"` // On a redirect, overwrite the Authority/Host portion of the URL with // this value. @@ -2042,9 +2071,17 @@ type HTTPRedirect struct { Scheme string `protobuf:"bytes,6,opt,name=scheme,proto3" json:"scheme,omitempty"` // On a redirect, Specifies the HTTP status code to use in the redirect // response. The default response code is MOVED_PERMANENTLY (301). - RedirectCode uint32 `protobuf:"varint,3,opt,name=redirect_code,json=redirectCode,proto3" json:"redirect_code,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache + RedirectCode uint32 `protobuf:"varint,3,opt,name=redirect_code,json=redirectCode,proto3" json:"redirect_code,omitempty"` + // Specifies how to rewrite the path on redirect. Exactly one of uri, + // prefix_rewrite, or uri_regex_rewrite may be set. + // + // Types that are valid to be assigned to PathRewriteSpecifier: + // + // *HTTPRedirect_PrefixRewrite + // *HTTPRedirect_UriRegexRewrite + PathRewriteSpecifier isHTTPRedirect_PathRewriteSpecifier `protobuf_oneof:"path_rewrite_specifier"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache } func (x *HTTPRedirect) Reset() { @@ -2130,6 +2167,31 @@ func (x *HTTPRedirect) GetRedirectCode() uint32 { return 0 } +func (x *HTTPRedirect) GetPathRewriteSpecifier() isHTTPRedirect_PathRewriteSpecifier { + if x != nil { + return x.PathRewriteSpecifier + } + return nil +} + +func (x *HTTPRedirect) GetPrefixRewrite() string { + if x != nil { + if x, ok := x.PathRewriteSpecifier.(*HTTPRedirect_PrefixRewrite); ok { + return x.PrefixRewrite + } + } + return "" +} + +func (x *HTTPRedirect) GetUriRegexRewrite() *RegexRewrite { + if x != nil { + if x, ok := x.PathRewriteSpecifier.(*HTTPRedirect_UriRegexRewrite); ok { + return x.UriRegexRewrite + } + } + return nil +} + type isHTTPRedirect_RedirectPort interface { isHTTPRedirect_RedirectPort() } @@ -2150,6 +2212,38 @@ func (*HTTPRedirect_Port) isHTTPRedirect_RedirectPort() {} func (*HTTPRedirect_DerivePort) isHTTPRedirect_RedirectPort() {} +type isHTTPRedirect_PathRewriteSpecifier interface { + isHTTPRedirect_PathRewriteSpecifier() +} + +type HTTPRedirect_PrefixRewrite struct { + // On a redirect, replace the matched prefix (or the entire path for exact + // matches) with this value. The route match must use a prefix match type. + // The matched prefix is stripped from the path and this value is prepended. + // + // Examples (route prefix match: /foo): + // - prefix_rewrite: /bar → /foo/baz becomes /bar/baz + // - prefix_rewrite: / → /foo/baz becomes //baz (use /foo/ match to get /baz) + // + // Mutually exclusive with uri and uri_regex_rewrite. + PrefixRewrite string `protobuf:"bytes,7,opt,name=prefix_rewrite,json=prefixRewrite,proto3,oneof"` +} + +type HTTPRedirect_UriRegexRewrite struct { + // On a redirect, rewrite the path portion of the URI with the specified + // RE2 regex. Capture groups in the pattern may be referenced in the + // replacement string. + // + // Example: match "^/foo(/.*)$" with rewrite "\\1" rewrites /foo/bar to /bar. + // + // Mutually exclusive with uri and prefix_rewrite. + UriRegexRewrite *RegexRewrite `protobuf:"bytes,8,opt,name=uri_regex_rewrite,json=uriRegexRewrite,proto3,oneof"` +} + +func (*HTTPRedirect_PrefixRewrite) isHTTPRedirect_PathRewriteSpecifier() {} + +func (*HTTPRedirect_UriRegexRewrite) isHTTPRedirect_PathRewriteSpecifier() {} + // HTTPDirectResponse can be used to send a fixed response to clients. // For example, the following rule returns a fixed 503 status with a body // to requests for /v1/getProductRatings API. @@ -3622,7 +3716,7 @@ const file_networking_v1alpha3_virtual_service_proto_rawDesc = "" + "\x10source_namespace\x18\a \x01(\tR\x0fsourceNamespace\x1a?\n" + "\x11SourceLabelsEntry\x12\x10\n" + "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + - "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01J\x04\b\x04\x10\x05R\rsource_subnet\"\xcf\x02\n" + + "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01J\x04\b\x04\x10\x05R\rsource_subnet\"\xe9\x03\n" + "\fHTTPRedirect\x12\x10\n" + "\x03uri\x18\x01 \x01(\tR\x03uri\x12\x1c\n" + "\tauthority\x18\x02 \x01(\tR\tauthority\x12\x14\n" + @@ -3630,11 +3724,14 @@ const file_networking_v1alpha3_virtual_service_proto_rawDesc = "" + "\vderive_port\x18\x05 \x01(\x0e2=.istio.networking.v1alpha3.HTTPRedirect.RedirectPortSelectionH\x00R\n" + "derivePort\x12\x16\n" + "\x06scheme\x18\x06 \x01(\tR\x06scheme\x12#\n" + - "\rredirect_code\x18\x03 \x01(\rR\fredirectCode\"I\n" + + "\rredirect_code\x18\x03 \x01(\rR\fredirectCode\x12'\n" + + "\x0eprefix_rewrite\x18\a \x01(\tH\x01R\rprefixRewrite\x12U\n" + + "\x11uri_regex_rewrite\x18\b \x01(\v2'.istio.networking.v1alpha3.RegexRewriteH\x01R\x0furiRegexRewrite\"I\n" + "\x15RedirectPortSelection\x12\x19\n" + "\x15FROM_PROTOCOL_DEFAULT\x10\x00\x12\x15\n" + "\x11FROM_REQUEST_PORT\x10\x01B\x0f\n" + - "\rredirect_port\"k\n" + + "\rredirect_portB\x18\n" + + "\x16path_rewrite_specifier\"k\n" + "\x12HTTPDirectResponse\x12\x1c\n" + "\x06status\x18\x01 \x01(\rB\x04\xe2A\x01\x02R\x06status\x127\n" + "\x04body\x18\x02 \x01(\v2#.istio.networking.v1alpha3.HTTPBodyR\x04body\"I\n" + @@ -3807,34 +3904,35 @@ var file_networking_v1alpha3_virtual_service_proto_depIdxs = []int32{ 33, // 36: istio.networking.v1alpha3.L4MatchAttributes.source_labels:type_name -> istio.networking.v1alpha3.L4MatchAttributes.SourceLabelsEntry 34, // 37: istio.networking.v1alpha3.TLSMatchAttributes.source_labels:type_name -> istio.networking.v1alpha3.TLSMatchAttributes.SourceLabelsEntry 0, // 38: istio.networking.v1alpha3.HTTPRedirect.derive_port:type_name -> istio.networking.v1alpha3.HTTPRedirect.RedirectPortSelection - 16, // 39: istio.networking.v1alpha3.HTTPDirectResponse.body:type_name -> istio.networking.v1alpha3.HTTPBody - 18, // 40: istio.networking.v1alpha3.HTTPRewrite.uri_regex_rewrite:type_name -> istio.networking.v1alpha3.RegexRewrite - 37, // 41: istio.networking.v1alpha3.HTTPRetry.per_try_timeout:type_name -> google.protobuf.Duration - 39, // 42: istio.networking.v1alpha3.HTTPRetry.retry_remote_localities:type_name -> google.protobuf.BoolValue - 39, // 43: istio.networking.v1alpha3.HTTPRetry.retry_ignore_previous_hosts:type_name -> google.protobuf.BoolValue - 37, // 44: istio.networking.v1alpha3.HTTPRetry.backoff:type_name -> google.protobuf.Duration - 19, // 45: istio.networking.v1alpha3.CorsPolicy.allow_origins:type_name -> istio.networking.v1alpha3.StringMatch - 37, // 46: istio.networking.v1alpha3.CorsPolicy.max_age:type_name -> google.protobuf.Duration - 39, // 47: istio.networking.v1alpha3.CorsPolicy.allow_credentials:type_name -> google.protobuf.BoolValue - 1, // 48: istio.networking.v1alpha3.CorsPolicy.unmatched_preflights:type_name -> istio.networking.v1alpha3.CorsPolicy.UnmatchedPreflights - 35, // 49: istio.networking.v1alpha3.HTTPFaultInjection.delay:type_name -> istio.networking.v1alpha3.HTTPFaultInjection.Delay - 36, // 50: istio.networking.v1alpha3.HTTPFaultInjection.abort:type_name -> istio.networking.v1alpha3.HTTPFaultInjection.Abort - 3, // 51: istio.networking.v1alpha3.HTTPMirrorPolicy.destination:type_name -> istio.networking.v1alpha3.Destination - 25, // 52: istio.networking.v1alpha3.HTTPMirrorPolicy.percentage:type_name -> istio.networking.v1alpha3.Percent - 27, // 53: istio.networking.v1alpha3.Headers.HeaderOperations.set:type_name -> istio.networking.v1alpha3.Headers.HeaderOperations.SetEntry - 28, // 54: istio.networking.v1alpha3.Headers.HeaderOperations.add:type_name -> istio.networking.v1alpha3.Headers.HeaderOperations.AddEntry - 19, // 55: istio.networking.v1alpha3.HTTPMatchRequest.HeadersEntry.value:type_name -> istio.networking.v1alpha3.StringMatch - 19, // 56: istio.networking.v1alpha3.HTTPMatchRequest.QueryParamsEntry.value:type_name -> istio.networking.v1alpha3.StringMatch - 19, // 57: istio.networking.v1alpha3.HTTPMatchRequest.WithoutHeadersEntry.value:type_name -> istio.networking.v1alpha3.StringMatch - 37, // 58: istio.networking.v1alpha3.HTTPFaultInjection.Delay.fixed_delay:type_name -> google.protobuf.Duration - 37, // 59: istio.networking.v1alpha3.HTTPFaultInjection.Delay.exponential_delay:type_name -> google.protobuf.Duration - 25, // 60: istio.networking.v1alpha3.HTTPFaultInjection.Delay.percentage:type_name -> istio.networking.v1alpha3.Percent - 25, // 61: istio.networking.v1alpha3.HTTPFaultInjection.Abort.percentage:type_name -> istio.networking.v1alpha3.Percent - 62, // [62:62] is the sub-list for method output_type - 62, // [62:62] is the sub-list for method input_type - 62, // [62:62] is the sub-list for extension type_name - 62, // [62:62] is the sub-list for extension extendee - 0, // [0:62] is the sub-list for field type_name + 18, // 39: istio.networking.v1alpha3.HTTPRedirect.uri_regex_rewrite:type_name -> istio.networking.v1alpha3.RegexRewrite + 16, // 40: istio.networking.v1alpha3.HTTPDirectResponse.body:type_name -> istio.networking.v1alpha3.HTTPBody + 18, // 41: istio.networking.v1alpha3.HTTPRewrite.uri_regex_rewrite:type_name -> istio.networking.v1alpha3.RegexRewrite + 37, // 42: istio.networking.v1alpha3.HTTPRetry.per_try_timeout:type_name -> google.protobuf.Duration + 39, // 43: istio.networking.v1alpha3.HTTPRetry.retry_remote_localities:type_name -> google.protobuf.BoolValue + 39, // 44: istio.networking.v1alpha3.HTTPRetry.retry_ignore_previous_hosts:type_name -> google.protobuf.BoolValue + 37, // 45: istio.networking.v1alpha3.HTTPRetry.backoff:type_name -> google.protobuf.Duration + 19, // 46: istio.networking.v1alpha3.CorsPolicy.allow_origins:type_name -> istio.networking.v1alpha3.StringMatch + 37, // 47: istio.networking.v1alpha3.CorsPolicy.max_age:type_name -> google.protobuf.Duration + 39, // 48: istio.networking.v1alpha3.CorsPolicy.allow_credentials:type_name -> google.protobuf.BoolValue + 1, // 49: istio.networking.v1alpha3.CorsPolicy.unmatched_preflights:type_name -> istio.networking.v1alpha3.CorsPolicy.UnmatchedPreflights + 35, // 50: istio.networking.v1alpha3.HTTPFaultInjection.delay:type_name -> istio.networking.v1alpha3.HTTPFaultInjection.Delay + 36, // 51: istio.networking.v1alpha3.HTTPFaultInjection.abort:type_name -> istio.networking.v1alpha3.HTTPFaultInjection.Abort + 3, // 52: istio.networking.v1alpha3.HTTPMirrorPolicy.destination:type_name -> istio.networking.v1alpha3.Destination + 25, // 53: istio.networking.v1alpha3.HTTPMirrorPolicy.percentage:type_name -> istio.networking.v1alpha3.Percent + 27, // 54: istio.networking.v1alpha3.Headers.HeaderOperations.set:type_name -> istio.networking.v1alpha3.Headers.HeaderOperations.SetEntry + 28, // 55: istio.networking.v1alpha3.Headers.HeaderOperations.add:type_name -> istio.networking.v1alpha3.Headers.HeaderOperations.AddEntry + 19, // 56: istio.networking.v1alpha3.HTTPMatchRequest.HeadersEntry.value:type_name -> istio.networking.v1alpha3.StringMatch + 19, // 57: istio.networking.v1alpha3.HTTPMatchRequest.QueryParamsEntry.value:type_name -> istio.networking.v1alpha3.StringMatch + 19, // 58: istio.networking.v1alpha3.HTTPMatchRequest.WithoutHeadersEntry.value:type_name -> istio.networking.v1alpha3.StringMatch + 37, // 59: istio.networking.v1alpha3.HTTPFaultInjection.Delay.fixed_delay:type_name -> google.protobuf.Duration + 37, // 60: istio.networking.v1alpha3.HTTPFaultInjection.Delay.exponential_delay:type_name -> google.protobuf.Duration + 25, // 61: istio.networking.v1alpha3.HTTPFaultInjection.Delay.percentage:type_name -> istio.networking.v1alpha3.Percent + 25, // 62: istio.networking.v1alpha3.HTTPFaultInjection.Abort.percentage:type_name -> istio.networking.v1alpha3.Percent + 63, // [63:63] is the sub-list for method output_type + 63, // [63:63] is the sub-list for method input_type + 63, // [63:63] is the sub-list for extension type_name + 63, // [63:63] is the sub-list for extension extendee + 0, // [0:63] is the sub-list for field type_name } func init() { file_networking_v1alpha3_virtual_service_proto_init() } @@ -3845,6 +3943,8 @@ func file_networking_v1alpha3_virtual_service_proto_init() { file_networking_v1alpha3_virtual_service_proto_msgTypes[12].OneofWrappers = []any{ (*HTTPRedirect_Port)(nil), (*HTTPRedirect_DerivePort)(nil), + (*HTTPRedirect_PrefixRewrite)(nil), + (*HTTPRedirect_UriRegexRewrite)(nil), } file_networking_v1alpha3_virtual_service_proto_msgTypes[14].OneofWrappers = []any{ (*HTTPBody_String_)(nil), diff --git a/networking/v1alpha3/virtual_service.pb.html b/networking/v1alpha3/virtual_service.pb.html index 637a497cc1..4c245dac40 100644 --- a/networking/v1alpha3/virtual_service.pb.html +++ b/networking/v1alpha3/virtual_service.pb.html @@ -1508,6 +1508,25 @@

HTTPRedirect

authority: newratings.default.svc.cluster.local ... +

The following rule redirects requests with a path prefix of /foo to the +authority foo.example.com, stripping the /foo prefix from the path:

+
apiVersion: networking.istio.io/v1
+kind: VirtualService
+metadata:
+  name: foo-redirect
+spec:
+  hosts:
+  - example.com
+  http:
+  - match:
+    - uri:
+        prefix: /foo/
+    redirect:
+      authority: foo.example.com
+      prefix_rewrite: /
+
+

With this rule, a request to example.com/foo/bar is redirected to +foo.example.com/bar.

@@ -1525,6 +1544,7 @@

HTTPRedirect

On a redirect, overwrite the Path portion of the URL with this value. Note that the entire path will be replaced, irrespective of the request URI being matched as an exact path or prefix.

+

Mutually exclusive with prefix_rewrite and uri_regex_rewrite.

@@ -1580,6 +1600,36 @@

HTTPRedirect

On a redirect, Specifies the HTTP status code to use in the redirect response. The default response code is MOVED_PERMANENTLY (301).

+ + + + + + + + + diff --git a/networking/v1alpha3/virtual_service.proto b/networking/v1alpha3/virtual_service.proto index d81ad2d72c..700c0c2cff 100644 --- a/networking/v1alpha3/virtual_service.proto +++ b/networking/v1alpha3/virtual_service.proto @@ -1074,10 +1074,35 @@ message TLSMatchAttributes { // ... // ``` // +// The following rule redirects requests with a path prefix of /foo to the +// authority foo.example.com, stripping the /foo prefix from the path: +// +// ```yaml +// apiVersion: networking.istio.io/v1 +// kind: VirtualService +// metadata: +// name: foo-redirect +// spec: +// hosts: +// - example.com +// http: +// - match: +// - uri: +// prefix: /foo/ +// redirect: +// authority: foo.example.com +// prefix_rewrite: / +// ``` +// +// With this rule, a request to example.com/foo/bar is redirected to +// foo.example.com/bar. +// message HTTPRedirect { // On a redirect, overwrite the Path portion of the URL with this // value. Note that the entire path will be replaced, irrespective of the // request URI being matched as an exact path or prefix. + // + // Mutually exclusive with prefix_rewrite and uri_regex_rewrite. string uri = 1; // On a redirect, overwrite the Authority/Host portion of the URL with @@ -1106,6 +1131,30 @@ message HTTPRedirect { // On a redirect, Specifies the HTTP status code to use in the redirect // response. The default response code is MOVED_PERMANENTLY (301). uint32 redirect_code = 3; + + // Specifies how to rewrite the path on redirect. Exactly one of uri, + // prefix_rewrite, or uri_regex_rewrite may be set. + oneof path_rewrite_specifier { + // On a redirect, replace the matched prefix (or the entire path for exact + // matches) with this value. The route match must use a prefix match type. + // The matched prefix is stripped from the path and this value is prepended. + // + // Examples (route prefix match: /foo): + // - prefix_rewrite: /bar → /foo/baz becomes /bar/baz + // - prefix_rewrite: / → /foo/baz becomes //baz (use /foo/ match to get /baz) + // + // Mutually exclusive with uri and uri_regex_rewrite. + string prefix_rewrite = 7; + + // On a redirect, rewrite the path portion of the URI with the specified + // RE2 regex. Capture groups in the pattern may be referenced in the + // replacement string. + // + // Example: match "^/foo(/.*)$" with rewrite "\\1" rewrites /foo/bar to /bar. + // + // Mutually exclusive with uri and prefix_rewrite. + RegexRewrite uri_regex_rewrite = 8; + } } // HTTPDirectResponse can be used to send a fixed response to clients. diff --git a/networking/v1beta1/virtual_service_alias.gen.go b/networking/v1beta1/virtual_service_alias.gen.go index 530098b3e5..eebe17ec8a 100644 --- a/networking/v1beta1/virtual_service_alias.gen.go +++ b/networking/v1beta1/virtual_service_alias.gen.go @@ -520,6 +520,33 @@ type TLSMatchAttributes = v1alpha3.TLSMatchAttributes // ... // // ``` +// +// The following rule redirects requests with a path prefix of /foo to the +// authority foo.example.com, stripping the /foo prefix from the path: +// +// ```yaml +// apiVersion: networking.istio.io/v1 +// kind: VirtualService +// metadata: +// +// name: foo-redirect +// +// spec: +// +// hosts: +// - example.com +// http: +// - match: +// - uri: +// prefix: /foo/ +// redirect: +// authority: foo.example.com +// prefix_rewrite: / +// +// ``` +// +// With this rule, a request to example.com/foo/bar is redirected to +// foo.example.com/bar. type HTTPRedirect = v1alpha3.HTTPRedirect type HTTPRedirect_RedirectPortSelection = v1alpha3.HTTPRedirect_RedirectPortSelection @@ -534,6 +561,26 @@ type HTTPRedirect_Port = v1alpha3.HTTPRedirect_Port // * FROM_REQUEST_PORT: automatically use the port of the request. type HTTPRedirect_DerivePort = v1alpha3.HTTPRedirect_DerivePort +// On a redirect, replace the matched prefix (or the entire path for exact +// matches) with this value. The route match must use a prefix match type. +// The matched prefix is stripped from the path and this value is prepended. +// +// Examples (route prefix match: /foo): +// - prefix_rewrite: /bar → /foo/baz becomes /bar/baz +// - prefix_rewrite: / → /foo/baz becomes //baz (use /foo/ match to get /baz) +// +// Mutually exclusive with uri and uri_regex_rewrite. +type HTTPRedirect_PrefixRewrite = v1alpha3.HTTPRedirect_PrefixRewrite + +// On a redirect, rewrite the path portion of the URI with the specified +// RE2 regex. Capture groups in the pattern may be referenced in the +// replacement string. +// +// Example: match "^/foo(/.*)$" with rewrite "\\1" rewrites /foo/bar to /bar. +// +// Mutually exclusive with uri and prefix_rewrite. +type HTTPRedirect_UriRegexRewrite = v1alpha3.HTTPRedirect_UriRegexRewrite + // HTTPDirectResponse can be used to send a fixed response to clients. // For example, the following rule returns a fixed 503 status with a body // to requests for /v1/getProductRatings API. diff --git a/releasenotes/notes/redirect-prefix-rewrite.yaml b/releasenotes/notes/redirect-prefix-rewrite.yaml new file mode 100644 index 0000000000..78ee66577d --- /dev/null +++ b/releasenotes/notes/redirect-prefix-rewrite.yaml @@ -0,0 +1,14 @@ +apiVersion: release-notes/v2 +kind: feature +area: traffic-management +issue: + - 47500 + - 47777 + - 52521 + +releaseNotes: + - | + **Added** `prefix_rewrite` and `uri_regex_rewrite` fields to `HTTPRedirect`, allowing redirects + that preserve the path suffix. `prefix_rewrite` replaces only the matched route prefix (e.g. + `example.com/foo/bar` → `foo.example.com/bar`); `uri_regex_rewrite` applies an RE2 regex + substitution. Both are mutually exclusive with the existing `uri` field.
+
string (oneof)
+
+

On a redirect, replace the matched prefix (or the entire path for exact +matches) with this value. The route match must use a prefix match type. +The matched prefix is stripped from the path and this value is prepended.

+

Examples (route prefix match: /foo):

+
    +
  • prefix_rewrite: /bar → /foo/baz becomes /bar/baz
  • +
  • prefix_rewrite: / → /foo/baz becomes //baz (use /foo/ match to get /baz)
  • +
+

Mutually exclusive with uri and uri_regex_rewrite.

+ +
+

On a redirect, rewrite the path portion of the URI with the specified +RE2 regex. Capture groups in the pattern may be referenced in the +replacement string.

+

Example: match “^/foo(/.*)$” with rewrite “\1” rewrites /foo/bar to /bar.

+

Mutually exclusive with uri and prefix_rewrite.

+