k8s_gateway_api/httproute.rs
1use crate::*;
2
3/// HTTPRoute provides a way to route HTTP requests. This includes the
4/// capability to match requests by hostname, path, header, or query param.
5/// Filters can be used to specify additional processing steps. Backends specify
6/// where matching requests should be routed.
7#[derive(
8 Clone,
9 Debug,
10 Default,
11 kube::CustomResource,
12 serde::Deserialize,
13 serde::Serialize,
14 schemars::JsonSchema,
15)]
16#[kube(
17 group = "gateway.networking.k8s.io",
18 version = "v1beta1",
19 kind = "HTTPRoute",
20 root = "HttpRoute",
21 status = "HttpRouteStatus",
22 namespaced
23)]
24pub struct HttpRouteSpec {
25 /// Common route information.
26 #[serde(flatten)]
27 pub inner: CommonRouteSpec,
28
29 /// Hostnames defines a set of hostname that should match against the HTTP
30 /// Host header to select a HTTPRoute to process the request. This matches
31 /// the RFC 1123 definition of a hostname with 2 notable exceptions:
32 ///
33 /// 1. IPs are not allowed.
34 /// 2. A hostname may be prefixed with a wildcard label (`*.`). The wildcard
35 /// label must appear by itself as the first label.
36 ///
37 /// If a hostname is specified by both the Listener and HTTPRoute, there
38 /// must be at least one intersecting hostname for the HTTPRoute to be
39 /// attached to the Listener. For example:
40 ///
41 /// * A Listener with `test.example.com` as the hostname matches HTTPRoutes
42 /// that have either not specified any hostnames, or have specified at
43 /// least one of `test.example.com` or `*.example.com`.
44 /// * A Listener with `*.example.com` as the hostname matches HTTPRoutes
45 /// that have either not specified any hostnames or have specified at least
46 /// one hostname that matches the Listener hostname. For example,
47 /// `test.example.com` and `*.example.com` would both match. On the other
48 /// hand, `example.com` and `test.example.net` would not match.
49 ///
50 /// If both the Listener and HTTPRoute have specified hostnames, any
51 /// HTTPRoute hostnames that do not match the Listener hostname MUST be
52 /// ignored. For example, if a Listener specified `*.example.com`, and the
53 /// HTTPRoute specified `test.example.com` and `test.example.net`,
54 /// `test.example.net` must not be considered for a match.
55 ///
56 /// If both the Listener and HTTPRoute have specified hostnames, and none
57 /// match with the criteria above, then the HTTPRoute is not accepted. The
58 /// implementation must raise an 'Accepted' Condition with a status of
59 /// `False` in the corresponding RouteParentStatus.
60 ///
61 /// Support: Core
62 pub hostnames: Option<Vec<Hostname>>,
63
64 /// Rules are a list of HTTP matchers, filters and actions.
65 pub rules: Option<Vec<HttpRouteRule>>,
66}
67
68/// HTTPRouteRule defines semantics for matching an HTTP request based on
69/// conditions (matches), processing it (filters), and forwarding the request to
70/// an API object (backendRefs).
71#[derive(
72 Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, schemars::JsonSchema,
73)]
74#[serde(rename_all = "camelCase")]
75pub struct HttpRouteRule {
76 /// Matches define conditions used for matching the rule against incoming
77 /// HTTP requests. Each match is independent, i.e. this rule will be matched
78 /// if **any** one of the matches is satisfied.
79 ///
80 /// For example, take the following matches configuration:
81 ///
82 /// ```yaml
83 /// matches:
84 /// - path:
85 /// value: "/foo"
86 /// headers:
87 /// - name: "version"
88 /// value: "v2"
89 /// - path:
90 /// value: "/v2/foo"
91 /// ```
92 ///
93 /// For a request to match against this rule, a request must satisfy
94 /// EITHER of the two conditions:
95 ///
96 /// - path prefixed with `/foo` AND contains the header `version: v2`
97 /// - path prefix of `/v2/foo`
98 ///
99 /// See the documentation for HTTPRouteMatch on how to specify multiple
100 /// match conditions that should be ANDed together.
101 ///
102 /// If no matches are specified, the default is a prefix
103 /// path match on "/", which has the effect of matching every
104 /// HTTP request.
105 ///
106 /// Proxy or Load Balancer routing configuration generated from HTTPRoutes
107 /// MUST prioritize rules based on the following criteria, continuing on
108 /// ties. Precedence must be given to the the Rule with the largest number
109 /// of:
110 ///
111 /// * Characters in a matching non-wildcard hostname.
112 /// * Characters in a matching hostname.
113 /// * Characters in a matching path.
114 /// * Header matches.
115 /// * Query param matches.
116 ///
117 /// If ties still exist across multiple Routes, matching precedence MUST be
118 /// determined in order of the following criteria, continuing on ties:
119 ///
120 /// * The oldest Route based on creation timestamp.
121 /// * The Route appearing first in alphabetical order by
122 /// "{namespace}/{name}".
123 ///
124 /// If ties still exist within the Route that has been given precedence,
125 /// matching precedence MUST be granted to the first matching rule meeting
126 /// the above criteria.
127 ///
128 /// When no rules matching a request have been successfully attached to the
129 /// parent a request is coming from, a HTTP 404 status code MUST be returned.
130 pub matches: Option<Vec<HttpRouteMatch>>,
131
132 /// Filters define the filters that are applied to requests that match this
133 /// rule.
134 ///
135 /// The effects of ordering of multiple behaviors are currently unspecified.
136 /// This can change in the future based on feedback during the alpha stage.
137 ///
138 /// Conformance-levels at this level are defined based on the type of
139 /// filter:
140 ///
141 /// - ALL core filters MUST be supported by all implementations.
142 /// - Implementers are encouraged to support extended filters.
143 /// - Implementation-specific custom filters have no API guarantees across
144 /// implementations.
145 ///
146 /// Specifying a core filter multiple times has unspecified or custom
147 /// conformance.
148 ///
149 /// Support: Core
150 pub filters: Option<Vec<HttpRouteFilter>>,
151
152 /// BackendRefs defines the backend(s) where matching requests should be
153 /// sent.
154 ///
155 /// A 500 status code MUST be returned if there are no BackendRefs or
156 /// filters specified that would result in a response being sent.
157 ///
158 /// A BackendRef is considered invalid when it refers to:
159 ///
160 /// * an unknown or unsupported kind of resource
161 /// * a resource that does not exist
162 /// * a resource in another namespace when the reference has not been
163 /// explicitly allowed by a ReferencePolicy (or equivalent concept).
164 ///
165 /// When a BackendRef is invalid, 500 status codes MUST be returned for
166 /// requests that would have otherwise been routed to an invalid backend. If
167 /// multiple backends are specified, and some are invalid, the proportion of
168 /// requests that would otherwise have been routed to an invalid backend
169 /// MUST receive a 500 status code.
170 ///
171 /// When a BackendRef refers to a Service that has no ready endpoints, it is
172 /// recommended to return a 503 status code.
173 ///
174 /// Support: Core for Kubernetes Service
175 /// Support: Custom for any other resource
176 ///
177 /// Support for weight: Core
178 pub backend_refs: Option<Vec<HttpBackendRef>>,
179}
180
181/// HTTPRouteMatch defines the predicate used to match requests to a given
182/// action. Multiple match types are ANDed together, i.e. the match will
183/// evaluate to true only if all conditions are satisfied.
184///
185/// For example, the match below will match a HTTP request only if its path
186/// starts with `/foo` AND it contains the `version: v1` header:
187///
188/// ```yaml
189/// match:
190/// path:
191/// value: "/foo"
192/// headers:
193/// - name: "version"
194/// value "v1"
195/// ```
196#[derive(
197 Clone, Debug, Default, Eq, PartialEq, serde::Deserialize, serde::Serialize, schemars::JsonSchema,
198)]
199#[serde(rename_all = "camelCase")]
200pub struct HttpRouteMatch {
201 /// Path specifies a HTTP request path matcher. If this field is not
202 /// specified, a default prefix match on the "/" path is provided.
203 pub path: Option<HttpPathMatch>,
204
205 /// Headers specifies HTTP request header matchers. Multiple match values
206 /// are ANDed together, meaning, a request must match all the specified
207 /// headers to select the route.
208 pub headers: Option<Vec<HttpHeaderMatch>>,
209
210 /// QueryParams specifies HTTP query parameter matchers. Multiple match
211 /// values are ANDed together, meaning, a request must match all the
212 /// specified query parameters to select the route.
213 pub query_params: Option<Vec<HttpQueryParamMatch>>,
214
215 /// Method specifies HTTP method matcher.
216 ///
217 /// When specified, this route will be matched only if the request has the
218 /// specified method.
219 ///
220 /// Support: Extended
221 pub method: Option<HttpMethod>,
222}
223
224/// HTTPPathMatch describes how to select a HTTP route by matching the HTTP request path.
225///
226/// The `type` specifies the semantics of how HTTP paths should be compared.
227/// Valid PathMatchType values are:
228///
229/// * "Exact"
230/// * "PathPrefix"
231/// * "RegularExpression"
232///
233/// PathPrefix and Exact paths must be syntactically valid:
234///
235/// - Must begin with the `/` character
236/// - Must not contain consecutive `/` characters (e.g. `/foo///`, `//`)
237#[derive(
238 Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, schemars::JsonSchema,
239)]
240#[serde(tag = "type", rename_all = "PascalCase")]
241pub enum HttpPathMatch {
242 Exact { value: String },
243 PathPrefix { value: String },
244 RegularExpression { value: String },
245}
246
247/// HTTPHeaderName is the name of an HTTP header.
248///
249/// Valid values include:
250///
251/// * "Authorization"
252/// * "Set-Cookie"
253///
254/// Invalid values include:
255///
256/// * ":method" - ":" is an invalid character. This means that HTTP/2 pseudo
257/// headers are not currently supported by this type.
258/// * "/invalid" - "/" is an invalid character
259pub type HttpHeaderName = String;
260
261/// HTTPHeaderMatch describes how to select a HTTP route by matching HTTP
262/// request headers.
263///
264/// `name` is the name of the HTTP Header to be matched. Name matching MUST be
265/// case insensitive. (See <https://tools.ietf.org/html/rfc7230#section-3.2>).
266///
267/// If multiple entries specify equivalent header names, only the first
268/// entry with an equivalent name MUST be considered for a match. Subsequent
269/// entries with an equivalent header name MUST be ignored. Due to the
270/// case-insensitivity of header names, "foo" and "Foo" are considered
271/// equivalent.
272///
273/// When a header is repeated in an HTTP request, it is
274/// implementation-specific behavior as to how this is represented.
275/// Generally, proxies should follow the guidance from the RFC:
276/// <https://www.rfc-editor.org/rfc/rfc7230.html#section-3.2.2> regarding
277/// processing a repeated header, with special handling for "Set-Cookie".
278#[derive(
279 Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, schemars::JsonSchema,
280)]
281#[serde(tag = "type", rename_all = "PascalCase")]
282pub enum HttpHeaderMatch {
283 #[serde(rename_all = "camelCase")]
284 Exact { name: HttpHeaderName, value: String },
285
286 #[serde(rename_all = "camelCase")]
287 RegularExpression {
288 name: HttpHeaderName,
289
290 /// Since RegularExpression HeaderMatchType has custom conformance,
291 /// implementations can support POSIX, PCRE or any other dialects of regular
292 /// expressions. Please read the implementation's documentation to determine
293 /// the supported dialect.
294 value: String,
295 },
296}
297
298/// HTTPQueryParamMatch describes how to select a HTTP route by matching HTTP
299/// query parameters.
300#[derive(
301 Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, schemars::JsonSchema,
302)]
303#[serde(tag = "type", rename_all = "PascalCase")]
304pub enum HttpQueryParamMatch {
305 #[serde(rename_all = "camelCase")]
306 Exact { name: String, value: String },
307
308 #[serde(rename_all = "camelCase")]
309 RegularExpression { name: String, value: String },
310}
311
312/// HTTPMethod describes how to select a HTTP route by matching the HTTP
313/// method as defined by
314/// [RFC 7231](https://datatracker.ietf.org/doc/html/rfc7231#section-4) and
315/// [RFC 5789](https://datatracker.ietf.org/doc/html/rfc5789#section-2).
316/// The value is expected in upper case.
317pub type HttpMethod = String;
318
319/// HTTPRouteFilter defines processing steps that must be completed during the
320/// request or response lifecycle. HTTPRouteFilters are meant as an extension
321/// point to express processing that may be done in Gateway implementations.
322/// Some examples include request or response modification, implementing
323/// authentication strategies, rate-limiting, and traffic shaping. API
324/// guarantee/conformance is defined based on the type of the filter.
325///
326/// Type identifies the type of filter to apply. As with other API fields,
327/// types are classified into three conformance levels:
328///
329/// - Core: Filter types and their corresponding configuration defined by
330/// "Support: Core" in this package, e.g. "RequestHeaderModifier". All
331/// implementations must support core filters.
332///
333/// - Extended: Filter types and their corresponding configuration defined by
334/// "Support: Extended" in this package, e.g. "RequestMirror". Implementers
335/// are encouraged to support extended filters.
336///
337/// - Custom: Filters that are defined and supported by specific vendors.
338/// In the future, filters showing convergence in behavior across multiple
339/// implementations will be considered for inclusion in extended or core
340/// conformance levels. Filter-specific configuration for such filters
341/// is specified using the ExtensionRef field. `Type` should be set to
342/// "ExtensionRef" for custom filters.
343///
344/// Implementers are encouraged to define custom implementation types to
345/// extend the core API with implementation-specific behavior.
346///
347/// If a reference to a custom filter type cannot be resolved, the filter
348/// MUST NOT be skipped. Instead, requests that would have been processed by
349/// that filter MUST receive a HTTP error response.
350#[derive(
351 Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, schemars::JsonSchema,
352)]
353#[serde(tag = "type", rename_all = "PascalCase")]
354pub enum HttpRouteFilter {
355 /// RequestHeaderModifier defines a schema for a filter that modifies request
356 /// headers.
357 ///
358 /// Support: Core
359 #[serde(rename_all = "camelCase")]
360 RequestHeaderModifier {
361 request_header_modifier: HttpRequestHeaderFilter,
362 },
363
364 /// ResponseHeaderModifier defines a schema for a filter that modifies
365 /// response headers.
366 ///
367 /// Support: Extended
368 #[serde(rename_all = "camelCase")]
369 ResponseHeaderModifier {
370 response_header_modifier: HttpRequestHeaderFilter,
371 },
372
373 /// RequestMirror defines a schema for a filter that mirrors requests.
374 /// Requests are sent to the specified destination, but responses from
375 /// that destination are ignored.
376 ///
377 /// Support: Extended
378 #[serde(rename_all = "camelCase")]
379 RequestMirror {
380 request_mirror: HttpRequestMirrorFilter,
381 },
382
383 /// RequestRedirect defines a schema for a filter that responds to the
384 /// request with an HTTP redirection.
385 ///
386 /// Support: Core
387 #[serde(rename_all = "camelCase")]
388 RequestRedirect {
389 request_redirect: HttpRequestRedirectFilter,
390 },
391
392 /// URLRewrite defines a schema for a filter that modifies a request during forwarding.
393 ///
394 /// Support: Extended
395 #[serde(rename_all = "camelCase")]
396 URLRewrite { url_rewrite: HttpUrlRewriteFilter },
397
398 /// ExtensionRef is an optional, implementation-specific extension to the
399 /// "filter" behavior. For example, resource "myroutefilter" in group
400 /// "networking.example.net"). ExtensionRef MUST NOT be used for core and
401 /// extended filters.
402 ///
403 /// Support: Implementation-specific
404 #[serde(rename_all = "camelCase")]
405 ExtensionRef { extension_ref: LocalObjectReference },
406}
407
408/// HTTPRequestHeaderFilter defines configuration for the RequestHeaderModifier
409/// filter.
410#[derive(
411 Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, schemars::JsonSchema,
412)]
413pub struct HttpRequestHeaderFilter {
414 /// Set overwrites the request with the given header (name, value)
415 /// before the action.
416 ///
417 /// Input:
418 /// GET /foo HTTP/1.1
419 /// my-header: foo
420 ///
421 /// Config:
422 /// set:
423 /// - name: "my-header"
424 /// value: "bar"
425 ///
426 /// Output:
427 /// GET /foo HTTP/1.1
428 /// my-header: bar
429 pub set: Option<Vec<HttpHeader>>,
430
431 /// Add adds the given header(s) (name, value) to the request
432 /// before the action. It appends to any existing values associated
433 /// with the header name.
434 ///
435 /// Input:
436 /// GET /foo HTTP/1.1
437 /// my-header: foo
438 ///
439 /// Config:
440 /// add:
441 /// - name: "my-header"
442 /// value: "bar"
443 ///
444 /// Output:
445 /// GET /foo HTTP/1.1
446 /// my-header: foo
447 /// my-header: bar
448 pub add: Option<Vec<HttpHeader>>,
449
450 /// Remove the given header(s) from the HTTP request before the action. The
451 /// value of Remove is a list of HTTP header names. Note that the header
452 /// names are case-insensitive (see
453 /// <https://datatracker.ietf.org/doc/html/rfc2616#section-4.2>).
454 ///
455 /// Input:
456 /// GET /foo HTTP/1.1
457 /// my-header1: foo
458 /// my-header2: bar
459 /// my-header3: baz
460 ///
461 /// Config:
462 /// remove: ["my-header1", "my-header3"]
463 ///
464 /// Output:
465 /// GET /foo HTTP/1.1
466 /// my-header2: bar
467 pub remove: Option<Vec<String>>,
468}
469
470/// HTTPHeader represents an HTTP Header name and value as defined by RFC 7230.
471#[derive(
472 Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, schemars::JsonSchema,
473)]
474pub struct HttpHeader {
475 /// Name is the name of the HTTP Header to be matched. Name matching MUST be
476 /// case insensitive. (See <https://tools.ietf.org/html/rfc7230#section-3.2>).
477 ///
478 /// If multiple entries specify equivalent header names, the first entry with
479 /// an equivalent name MUST be considered for a match. Subsequent entries
480 /// with an equivalent header name MUST be ignored. Due to the
481 /// case-insensitivity of header names, "foo" and "Foo" are considered
482 /// equivalent.
483 pub name: HttpHeaderName,
484
485 /// Value is the value of HTTP Header to be matched.
486 pub value: String,
487}
488
489/// HTTPPathModifier defines configuration for path modifiers.
490///
491// gateway:experimental
492#[derive(
493 Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, schemars::JsonSchema,
494)]
495#[serde(tag = "type", rename_all = "PascalCase")]
496pub enum HttpPathModifier {
497 /// ReplaceFullPath specifies the value with which to replace the full path
498 /// of a request during a rewrite or redirect.
499 #[serde(rename_all = "camelCase")]
500 ReplaceFullPath { replace_full_path: String },
501
502 /// ReplacePrefixMatch specifies the value with which to replace the prefix
503 /// match of a request during a rewrite or redirect. For example, a request
504 /// to "/foo/bar" with a prefix match of "/foo" would be modified to "/bar".
505 #[serde(rename_all = "camelCase")]
506 ReplacePrefixMatch { replace_prefix_match: String },
507}
508
509/// HTTPRequestRedirect defines a filter that redirects a request. This filter
510/// MUST not be used on the same Route rule as a HTTPURLRewrite filter.
511#[derive(
512 Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, schemars::JsonSchema,
513)]
514#[serde(rename_all = "camelCase")]
515pub struct HttpRequestRedirectFilter {
516 /// Scheme is the scheme to be used in the value of the `Location`
517 /// header in the response.
518 /// When empty, the scheme of the request is used.
519 ///
520 /// Support: Extended
521 pub scheme: Option<String>,
522
523 /// Hostname is the hostname to be used in the value of the `Location`
524 /// header in the response.
525 ///
526 /// When empty, the hostname of the request is used.
527 ///
528 /// Support: Core
529 pub hostname: Option<PreciseHostname>,
530
531 /// Path defines parameters used to modify the path of the incoming request.
532 /// The modified path is then used to construct the `Location` header. When
533 /// empty, the request path is used as-is.
534 ///
535 /// Support: Extended
536 pub path: Option<HttpPathModifier>,
537
538 /// Port is the port to be used in the value of the `Location`
539 /// header in the response.
540 /// When empty, port (if specified) of the request is used.
541 ///
542 /// Support: Extended
543 pub port: Option<PortNumber>,
544
545 /// StatusCode is the HTTP status code to be used in response.
546 ///
547 /// Support: Core
548 pub status_code: Option<u16>,
549}
550
551/// HTTPURLRewriteFilter defines a filter that modifies a request during
552/// forwarding. At most one of these filters may be used on a Route rule. This
553/// may not be used on the same Route rule as a HTTPRequestRedirect filter.
554///
555/// gateway:experimental
556/// Support: Extended
557#[derive(
558 Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, schemars::JsonSchema,
559)]
560pub struct HttpUrlRewriteFilter {
561 /// Hostname is the value to be used to replace the Host header value during
562 /// forwarding.
563 ///
564 /// Support: Extended
565 pub hostname: Option<PreciseHostname>,
566
567 /// Path defines a path rewrite.
568 ///
569 /// Support: Extended
570 pub path: Option<HttpPathModifier>,
571}
572
573/// HTTPRequestMirrorFilter defines configuration for the RequestMirror filter.
574#[derive(
575 Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, schemars::JsonSchema,
576)]
577#[serde(rename_all = "camelCase")]
578pub struct HttpRequestMirrorFilter {
579 /// BackendRef references a resource where mirrored requests are sent.
580 ///
581 /// If the referent cannot be found, this BackendRef is invalid and must be
582 /// dropped from the Gateway. The controller must ensure the "ResolvedRefs"
583 /// condition on the Route status is set to `status: False` and not configure
584 /// this backend in the underlying implementation.
585 ///
586 /// If there is a cross-namespace reference to an *existing* object
587 /// that is not allowed by a ReferencePolicy, the controller must ensure the
588 /// "ResolvedRefs" condition on the Route is set to `status: False`,
589 /// with the "RefNotPermitted" reason and not configure this backend in the
590 /// underlying implementation.
591 ///
592 /// In either error case, the Message of the `ResolvedRefs` Condition
593 /// should be used to provide more detail about the problem.
594 ///
595 /// Support: Extended for Kubernetes Service
596 /// Support: Custom for any other resource
597 pub backend_ref: BackendObjectReference,
598}
599
600/// HTTPBackendRef defines how a HTTPRoute should forward an HTTP request.
601#[derive(
602 Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, schemars::JsonSchema,
603)]
604#[serde(rename_all = "camelCase")]
605pub struct HttpBackendRef {
606 /// BackendRef is a reference to a backend to forward matched requests to.
607 ///
608 /// If the referent cannot be found, this HTTPBackendRef is invalid and must
609 /// be dropped from the Gateway. The controller must ensure the
610 /// "ResolvedRefs" condition on the Route is set to `status: False` and not
611 /// configure this backend in the underlying implementation.
612 ///
613 /// If there is a cross-namespace reference to an *existing* object
614 /// that is not covered by a ReferencePolicy, the controller must ensure the
615 /// "ResolvedRefs" condition on the Route is set to `status: False`,
616 /// with the "RefNotPermitted" reason and not configure this backend in the
617 /// underlying implementation.
618 ///
619 /// In either error case, the Message of the `ResolvedRefs` Condition
620 /// should be used to provide more detail about the problem.
621 ///
622 /// Support: Custom
623 #[serde(flatten)]
624 pub backend_ref: Option<BackendRef>,
625
626 /// Filters defined at this level should be executed if and only if the
627 /// request is being forwarded to the backend defined here.
628 ///
629 /// Support: Custom (For broader support of filters, use the Filters field
630 /// in HTTPRouteRule.)
631 pub filters: Option<Vec<HttpRouteFilter>>,
632}
633
634/// HTTPRouteStatus defines the observed state of HTTPRoute.
635#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize, schemars::JsonSchema)]
636pub struct HttpRouteStatus {
637 /// Common route status information.
638 #[serde(flatten)]
639 pub inner: RouteStatus,
640}
641
642#[cfg(test)]
643mod test {
644 use super::*;
645
646 #[test]
647 fn test_deserialize_http_route() {
648 // Test json with a URLRewrote
649 let test_json = r#"{
650 "apiVersion":"gateway.networking.k8s.io/v1beta1",
651 "kind":"HTTPRoute",
652 "metadata":{"name":"route_name"},
653 "spec":{
654 "parentRefs":null,
655 "hostnames":null,
656 "rules":[{
657 "matches":null,
658 "filters":[{
659 "type":"URLRewrite",
660 "urlRewrite":{
661 "hostname":null,
662 "path":{
663 "type":"ReplacePrefixMatch",
664 "replacePrefixMatch":"/"
665 }
666 }
667 }],
668 "backendRefs":null
669 }]}}"#;
670 let route: Result<HttpRoute, _> = serde_json::from_str(test_json);
671 assert!(route.is_ok());
672 }
673}