Skip to content

Commit 9eecf12

Browse files
committed
fix: use trim() in CEL rule to reject whitespace-only name for non-Path scopes
Addresses reviewer feedback: the previous rule 'size(self.name) > 0' would accept names like ' ' which would produce an invalid APISIX variable 'post_arg. '. Using trim() ensures blank-only names are rejected. The has(self.name) guard is not needed because non-nullable string fields resolve to "" (zero value) in Kubernetes CEL when omitted, as confirmed by existing tests.
1 parent a03d90d commit 9eecf12

4 files changed

Lines changed: 145 additions & 5 deletions

File tree

api/v2/apisixroute_types.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -411,7 +411,7 @@ type ApisixRouteAuthenticationLDAPAuth struct {
411411
}
412412

413413
// ApisixRouteHTTPMatchExprSubject describes the subject of a route matching expression.
414-
// +kubebuilder:validation:XValidation:rule="self.scope == 'Path' || size(self.name) > 0",message="name is required when scope is not Path"
414+
// +kubebuilder:validation:XValidation:rule="self.scope == 'Path' || size(self.name.trim()) > 0",message="name is required and must not be blank when scope is not Path"
415415
type ApisixRouteHTTPMatchExprSubject struct {
416416
// Scope specifies the subject scope.
417417
// Supported values: `Header`, `Query`, `Path`, `Cookie`, `Variable`, `Body`.

api/v2/apisixroute_types_test.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,16 @@ func TestApisixRoute_BodyScope_EmptyName(t *testing.T) {
9090
v := loadApisixRouteSchema(t)
9191
err := v.Validate(t, newRouteWithBodyExpr("apisix", "", "login"))
9292
require.Error(t, err)
93-
assert.Contains(t, err.Error(), "name is required when scope is not Path")
93+
assert.Contains(t, err.Error(), "name is required and must not be blank when scope is not Path")
94+
}
95+
96+
// TestApisixRoute_BodyScope_WhitespaceName verifies that a Body scope expr with
97+
// a whitespace-only name is rejected (trim() prevents blank names from passing).
98+
func TestApisixRoute_BodyScope_WhitespaceName(t *testing.T) {
99+
v := loadApisixRouteSchema(t)
100+
err := v.Validate(t, newRouteWithBodyExpr("apisix", " ", "login"))
101+
require.Error(t, err)
102+
assert.Contains(t, err.Error(), "name is required and must not be blank when scope is not Path")
94103
}
95104

96105
// TestApisixRoute_PathScope_EmptyName verifies that Path scope without a name

config/crd/bases/apisix.apache.org_apisixroutes.yaml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -231,9 +231,10 @@ spec:
231231
- scope
232232
type: object
233233
x-kubernetes-validations:
234-
- message: name is required when scope is not Path
235-
rule: self.scope == 'Path' || size(self.name) >
236-
0
234+
- message: name is required and must not be blank
235+
when scope is not Path
236+
rule: self.scope == 'Path' || size(self.name.trim())
237+
> 0
237238
value:
238239
description: |-
239240
Value defines a single value to compare against the subject.

docs/en/latest/reference/api-reference.md

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,66 @@ PluginConfig defines plugin configuration.
103103
### Types
104104

105105
This section describes the types used by the CRDs.
106+
#### ActiveHealthCheck
107+
108+
109+
ActiveHealthCheck defines the active upstream health check configuration.
110+
111+
112+
113+
| Field | Description |
114+
| --- | --- |
115+
| `type` _string_ | Type is the health check type. Can be `http`, `https`, or `tcp`. |
116+
| `timeout` _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#duration-v1-meta)_ | Timeout sets health check timeout. |
117+
| `concurrency` _integer_ | Concurrency sets the number of targets to be checked at the same time. |
118+
| `host` _string_ | Host sets the upstream host used in the health check request. |
119+
| `port` _integer_ | Port sets the port on the upstream node to probe. |
120+
| `httpPath` _string_ | HTTPPath sets the HTTP path for the probe request. |
121+
| `strictTLS` _boolean_ | StrictTLS controls whether TLS certificate validation is enforced. |
122+
| `requestHeaders` _string array_ | RequestHeaders sets additional HTTP request headers for the probe. |
123+
| `healthy` _[ActiveHealthCheckHealthy](#activehealthcheckhealthy)_ | Healthy configures the thresholds for marking a node healthy. |
124+
| `unhealthy` _[ActiveHealthCheckUnhealthy](#activehealthcheckunhealthy)_ | Unhealthy configures the thresholds for marking a node unhealthy. |
125+
126+
127+
_Appears in:_
128+
- [HealthCheck](#healthcheck)
129+
130+
#### ActiveHealthCheckHealthy
131+
132+
133+
ActiveHealthCheckHealthy defines thresholds for actively marking an upstream node healthy.
134+
135+
136+
137+
| Field | Description |
138+
| --- | --- |
139+
| `httpCodes` _integer array_ | HTTPCodes is the list of HTTP status codes considered healthy. |
140+
| `successes` _integer_ | Successes is the number of consecutive successful responses required to mark a node healthy. |
141+
| `interval` _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#duration-v1-meta)_ | Interval defines the time between health check probes. Minimum is 1s. |
142+
143+
144+
_Appears in:_
145+
- [ActiveHealthCheck](#activehealthcheck)
146+
147+
#### ActiveHealthCheckUnhealthy
148+
149+
150+
ActiveHealthCheckUnhealthy defines thresholds for actively marking an upstream node unhealthy.
151+
152+
153+
154+
| Field | Description |
155+
| --- | --- |
156+
| `httpCodes` _integer array_ | HTTPCodes is the list of HTTP status codes considered unhealthy. |
157+
| `httpFailures` _integer_ | HTTPFailures is the number of HTTP failures to mark a node unhealthy. |
158+
| `tcpFailures` _integer_ | TCPFailures is the number of TCP failures to mark a node unhealthy. |
159+
| `timeout` _integer_ | Timeouts is the number of timeouts to mark a node unhealthy. |
160+
| `interval` _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#duration-v1-meta)_ | Interval defines the time between health check probes. Minimum is 1s. |
161+
162+
163+
_Appears in:_
164+
- [ActiveHealthCheck](#activehealthcheck)
165+
106166
#### AdminKeyAuth
107167

108168

@@ -180,6 +240,7 @@ _Appears in:_
180240
| `timeout` _[Timeout](#timeout)_ | Timeout sets the read, send, and connect timeouts to the upstream. |
181241
| `passHost` _string_ | PassHost configures how the host header should be determined when a request is forwarded to the upstream. Default is `pass`. Can be `pass`, `node` or `rewrite`:<br /> • `pass`: preserve the original Host header<br /> • `node`: use the upstream node’s host<br /> • `rewrite`: set to a custom host via `upstreamHost` |
182242
| `upstreamHost` _[Hostname](#hostname)_ | UpstreamHost specifies the host of the Upstream request. Used only if passHost is set to `rewrite`. |
243+
| `healthCheck` _[HealthCheck](#healthcheck)_ | HealthCheck defines active and passive health check configuration for the upstream backends. When configured, APISIX will probe backends (active) or monitor live traffic (passive) to detect and bypass unhealthy nodes. |
183244

184245

185246
_Appears in:_
@@ -344,6 +405,22 @@ HTTPRoutePolicySpec defines the desired state of HTTPRoutePolicy.
344405
_Appears in:_
345406
- [HTTPRoutePolicy](#httproutepolicy)
346407

408+
#### HealthCheck
409+
410+
411+
HealthCheck defines the active and passive health check configuration for upstream nodes.
412+
413+
414+
415+
| Field | Description |
416+
| --- | --- |
417+
| `active` _[ActiveHealthCheck](#activehealthcheck)_ | Active health checks proactively send requests to upstream nodes to determine their availability. |
418+
| `passive` _[PassiveHealthCheck](#passivehealthcheck)_ | Passive health checks evaluate upstream health based on observed traffic (timeouts, errors). |
419+
420+
421+
_Appears in:_
422+
- [BackendTrafficPolicySpec](#backendtrafficpolicyspec)
423+
347424
#### Hostname
348425
_Base type:_ `string`
349426

@@ -373,6 +450,59 @@ LoadBalancer describes the load balancing parameters.
373450
_Appears in:_
374451
- [BackendTrafficPolicySpec](#backendtrafficpolicyspec)
375452

453+
#### PassiveHealthCheck
454+
455+
456+
PassiveHealthCheck defines passive health check configuration based on observed traffic.
457+
458+
459+
460+
| Field | Description |
461+
| --- | --- |
462+
| `type` _string_ | Type is the passive health check type. Can be `http`, `https`, or `tcp`. |
463+
| `healthy` _[PassiveHealthCheckHealthy](#passivehealthcheckhealthy)_ | Healthy defines conditions under which a node is considered healthy. |
464+
| `unhealthy` _[PassiveHealthCheckUnhealthy](#passivehealthcheckunhealthy)_ | Unhealthy defines conditions under which a node is considered unhealthy. |
465+
466+
467+
_Appears in:_
468+
- [HealthCheck](#healthcheck)
469+
470+
#### PassiveHealthCheckHealthy
471+
472+
473+
PassiveHealthCheckHealthy defines conditions for passively marking a node healthy.
474+
475+
476+
477+
| Field | Description |
478+
| --- | --- |
479+
| `httpCodes` _integer array_ | HTTPCodes is the list of HTTP status codes considered healthy. |
480+
| `successes` _integer_ | Successes is the number of consecutive successful responses required to mark a node healthy. |
481+
482+
483+
_Appears in:_
484+
- [ActiveHealthCheckHealthy](#activehealthcheckhealthy)
485+
- [PassiveHealthCheck](#passivehealthcheck)
486+
487+
#### PassiveHealthCheckUnhealthy
488+
489+
490+
PassiveHealthCheckUnhealthy defines conditions for passively marking a node unhealthy.
491+
492+
493+
494+
| Field | Description |
495+
| --- | --- |
496+
| `httpCodes` _integer array_ | HTTPCodes is the list of HTTP status codes considered unhealthy. |
497+
| `httpFailures` _integer_ | HTTPFailures is the number of HTTP failures to mark a node unhealthy. |
498+
| `tcpFailures` _integer_ | TCPFailures is the number of TCP failures to mark a node unhealthy. |
499+
| `timeout` _integer_ | Timeouts is the number of timeouts to mark a node unhealthy. |
500+
501+
502+
_Appears in:_
503+
- [ActiveHealthCheckUnhealthy](#activehealthcheckunhealthy)
504+
- [PassiveHealthCheck](#passivehealthcheck)
505+
376506
#### Plugin
377507

378508

0 commit comments

Comments
 (0)