Skip to content

Commit 3cbb4ca

Browse files
committed
fix: replace trim() CEL rule with Pattern annotation to avoid cost budget error
trim() in CEL has O(n) cost; without maxLength the estimator assumed unbounded string length and rejected the rule with '100x budget exceeded'. Split the concern into two zero-cost constraints: - CEL XValidation: 'self.scope == Path || size(self.name) > 0' (O(1), unchanged) - Pattern: '^$|.*\S.*' (OpenAPI schema level, no CEL cost) rejects whitespace-only names while allowing empty string (Path scope)
1 parent 9eecf12 commit 3cbb4ca

3 files changed

Lines changed: 9 additions & 8 deletions

File tree

api/v2/apisixroute_types.go

Lines changed: 2 additions & 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.trim()) > 0",message="name is required and must not be blank when scope is not Path"
414+
// +kubebuilder:validation:XValidation:rule="self.scope == 'Path' || size(self.name) > 0",message="name is required when scope is not Path"
415415
type ApisixRouteHTTPMatchExprSubject struct {
416416
// Scope specifies the subject scope.
417417
// Supported values: `Header`, `Query`, `Path`, `Cookie`, `Variable`, `Body`.
@@ -425,6 +425,7 @@ type ApisixRouteHTTPMatchExprSubject struct {
425425
// parameter name, cookie name, Nginx variable name, or body field name (dot-notation
426426
// JSON path supported for Body scope). Optional when Scope is Path.
427427
// +kubebuilder:validation:Optional
428+
// +kubebuilder:validation:Pattern=`^$|.*\S.*`
428429
Name string `json:"name,omitempty" yaml:"name,omitempty"`
429430
}
430431

api/v2/apisixroute_types_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,16 +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 and must not be blank when scope is not Path")
93+
assert.Contains(t, err.Error(), "name is required when scope is not Path")
9494
}
9595

9696
// TestApisixRoute_BodyScope_WhitespaceName verifies that a Body scope expr with
97-
// a whitespace-only name is rejected (trim() prevents blank names from passing).
97+
// a whitespace-only name is rejected by the Pattern constraint on the name field.
9898
func TestApisixRoute_BodyScope_WhitespaceName(t *testing.T) {
9999
v := loadApisixRouteSchema(t)
100100
err := v.Validate(t, newRouteWithBodyExpr("apisix", " ", "login"))
101101
require.Error(t, err)
102-
assert.Contains(t, err.Error(), "name is required and must not be blank when scope is not Path")
102+
assert.Contains(t, err.Error(), "name")
103103
}
104104

105105
// TestApisixRoute_PathScope_EmptyName verifies that Path scope without a name

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,7 @@ spec:
210210
Name is the name of the subject within the given scope: the header name, query
211211
parameter name, cookie name, Nginx variable name, or body field name (dot-notation
212212
JSON path supported for Body scope). Optional when Scope is Path.
213+
pattern: ^$|.*\S.*
213214
type: string
214215
scope:
215216
description: |-
@@ -231,10 +232,9 @@ spec:
231232
- scope
232233
type: object
233234
x-kubernetes-validations:
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
235+
- message: name is required when scope is not Path
236+
rule: self.scope == 'Path' || size(self.name) >
237+
0
238238
value:
239239
description: |-
240240
Value defines a single value to compare against the subject.

0 commit comments

Comments
 (0)