feat: support Body scope in ApisixRoute HTTP match expressions#415
feat: support Body scope in ApisixRoute HTTP match expressions#415AlinsRan wants to merge 1 commit into
Conversation
Adds support for matching on request body fields in ApisixRoute, mapping to APISIX's post_arg.<name> variable. Supports application/json (with dot-notation JSON path), application/x-www-form-urlencoded, and multipart/form-data content types. - Add ScopeBody constant to shared_types.go - Add ToVars() case for ScopeBody mapping to post_arg.<name> - Add Body to Scope enum validation marker - Add CEL XValidation: name required when scope is not Path - Make Name field optional (omitempty) since Path scope needs no name - Add shared CRD schema validator for unit tests (crd_schema_validator_test.go) - Migrate ApisixConsumer validation tests to shared validator - Add ApisixRoute body scope unit tests - Regenerate CRD manifest and API reference docs Synced from apache/apisix-ingress-controller#2762
📝 WalkthroughWalkthroughThis PR introduces request body field matching capability for ApisixRoute HTTP match expressions. The core addition is a new ChangesBody Scope Feature
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related issues
Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 5 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Pull request overview
This PR adds Body as a supported scope in ApisixRoute HTTP match expressions, translating it to APISIX’s post_arg.<name> variable, and updates the CRD schema/docs/tests accordingly.
Changes:
- Add
ScopeBodyand mapBodyscope inApisixRouteHTTPMatchExprs.ToVars()topost_arg.<name>. - Update
ApisixRouteHTTPMatchExprSubjectCRD schema: expand enum (incl.Body), makenameoptional forPath, and enforcenamevia CEL validation for non-Pathscopes. - Add shared CRD schema validator test helper and add/adjust unit tests for CRD validation.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| docs/en/latest/reference/api-reference.md | Updates API reference to document new Body scope and revised subject docs link. |
| config/crd/bases/apisix.apache.org_apisixroutes.yaml | Updates CRD schema to include Body scope + CEL validation for name. |
| api/v2/shared_types.go | Adds ScopeBody constant and documentation. |
| api/v2/crd_schema_validator_test.go | Introduces shared validator used by CRD schema validation tests. |
| api/v2/apisixroute_types.go | Adds Body scope handling in ToVars() and updates subject validation/tags. |
| api/v2/apisixroute_types_test.go | Adds CRD validation tests for Body scope and name requirement behavior. |
| api/v2/apisixconsumer_validation_test.go | Refactors tests to use shared CRD schema validator. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
🧹 Nitpick comments (1)
api/v2/apisixconsumer_validation_test.go (1)
29-35: LGTM!Good refactoring that eliminates code duplication by delegating to the shared
loadCRDSchemahelper. The path construction usingruntime.Callerandfilepath.Joinis correct and maintains the same behavior as before.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@api/v2/apisixconsumer_validation_test.go` around lines 29 - 35, No change required: the refactor of loadApisixConsumerSchema to delegate to the shared loadCRDSchema is correct—keep the implementation of loadApisixConsumerSchema as-is (it uses runtime.Caller and filepath.Join to build crdPath and returns loadCRDSchema(t, crdPath)).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@api/v2/apisixconsumer_validation_test.go`:
- Around line 29-35: No change required: the refactor of
loadApisixConsumerSchema to delegate to the shared loadCRDSchema is correct—keep
the implementation of loadApisixConsumerSchema as-is (it uses runtime.Caller and
filepath.Join to build crdPath and returns loadCRDSchema(t, crdPath)).
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 0cbf350f-cd47-4940-a39e-b6e7195706a4
📒 Files selected for processing (7)
api/v2/apisixconsumer_validation_test.goapi/v2/apisixroute_types.goapi/v2/apisixroute_types_test.goapi/v2/crd_schema_validator_test.goapi/v2/shared_types.goconfig/crd/bases/apisix.apache.org_apisixroutes.yamldocs/en/latest/reference/api-reference.md
conformance test report - apisix modeapiVersion: gateway.networking.k8s.io/v1
date: "2026-05-12T06:40:33Z"
gatewayAPIChannel: experimental
gatewayAPIVersion: v1.3.0
implementation:
contact: null
organization: APISIX
project: apisix-ingress-controller
url: https://github.com/apache/apisix-ingress-controller.git
version: v2.0.0
kind: ConformanceReport
mode: default
profiles:
- core:
result: success
statistics:
Failed: 0
Passed: 12
Skipped: 0
name: GATEWAY-GRPC
summary: Core tests succeeded.
- core:
failedTests:
- HTTPRouteInvalidBackendRefUnknownKind
result: failure
skippedTests:
- HTTPRouteHTTPSListener
statistics:
Failed: 1
Passed: 31
Skipped: 1
extended:
result: partial
skippedTests:
- HTTPRouteRedirectPortAndScheme
statistics:
Failed: 0
Passed: 11
Skipped: 1
supportedFeatures:
- GatewayAddressEmpty
- GatewayPort8080
- HTTPRouteBackendProtocolWebSocket
- HTTPRouteDestinationPortMatching
- HTTPRouteHostRewrite
- HTTPRouteMethodMatching
- HTTPRoutePathRewrite
- HTTPRoutePortRedirect
- HTTPRouteQueryParamMatching
- HTTPRouteRequestMirror
- HTTPRouteResponseHeaderModification
- HTTPRouteSchemeRedirect
unsupportedFeatures:
- GatewayHTTPListenerIsolation
- GatewayInfrastructurePropagation
- GatewayStaticAddresses
- HTTPRouteBackendProtocolH2C
- HTTPRouteBackendRequestHeaderModification
- HTTPRouteBackendTimeout
- HTTPRouteParentRefPort
- HTTPRoutePathRedirect
- HTTPRouteRequestMultipleMirrors
- HTTPRouteRequestPercentageMirror
- HTTPRouteRequestTimeout
name: GATEWAY-HTTP
summary: Core tests failed with 1 test failures. Extended tests partially succeeded
with 1 test skips.
- core:
result: partial
skippedTests:
- TLSRouteSimpleSameNamespace
statistics:
Failed: 0
Passed: 10
Skipped: 1
name: GATEWAY-TLS
summary: Core tests partially succeeded with 1 test skips. |
conformance test report - apisix-standalone modeapiVersion: gateway.networking.k8s.io/v1
date: "2026-05-12T06:40:50Z"
gatewayAPIChannel: experimental
gatewayAPIVersion: v1.3.0
implementation:
contact: null
organization: APISIX
project: apisix-ingress-controller
url: https://github.com/apache/apisix-ingress-controller.git
version: v2.0.0
kind: ConformanceReport
mode: default
profiles:
- core:
result: success
statistics:
Failed: 0
Passed: 12
Skipped: 0
name: GATEWAY-GRPC
summary: Core tests succeeded.
- core:
result: partial
skippedTests:
- HTTPRouteHTTPSListener
statistics:
Failed: 0
Passed: 32
Skipped: 1
extended:
result: partial
skippedTests:
- HTTPRouteRedirectPortAndScheme
statistics:
Failed: 0
Passed: 11
Skipped: 1
supportedFeatures:
- GatewayAddressEmpty
- GatewayPort8080
- HTTPRouteBackendProtocolWebSocket
- HTTPRouteDestinationPortMatching
- HTTPRouteHostRewrite
- HTTPRouteMethodMatching
- HTTPRoutePathRewrite
- HTTPRoutePortRedirect
- HTTPRouteQueryParamMatching
- HTTPRouteRequestMirror
- HTTPRouteResponseHeaderModification
- HTTPRouteSchemeRedirect
unsupportedFeatures:
- GatewayHTTPListenerIsolation
- GatewayInfrastructurePropagation
- GatewayStaticAddresses
- HTTPRouteBackendProtocolH2C
- HTTPRouteBackendRequestHeaderModification
- HTTPRouteBackendTimeout
- HTTPRouteParentRefPort
- HTTPRoutePathRedirect
- HTTPRouteRequestMultipleMirrors
- HTTPRouteRequestPercentageMirror
- HTTPRouteRequestTimeout
name: GATEWAY-HTTP
summary: Core tests partially succeeded with 1 test skips. Extended tests partially
succeeded with 1 test skips.
- core:
result: partial
skippedTests:
- TLSRouteSimpleSameNamespace
statistics:
Failed: 0
Passed: 10
Skipped: 1
name: GATEWAY-TLS
summary: Core tests partially succeeded with 1 test skips. |
conformance test reportapiVersion: gateway.networking.k8s.io/v1
date: "2026-05-12T07:00:44Z"
gatewayAPIChannel: experimental
gatewayAPIVersion: v1.3.0
implementation:
contact: null
organization: APISIX
project: apisix-ingress-controller
url: https://github.com/apache/apisix-ingress-controller.git
version: v2.0.0
kind: ConformanceReport
mode: default
profiles:
- core:
failedTests:
- GRPCExactMethodMatching
- GRPCRouteHeaderMatching
- GRPCRouteListenerHostnameMatching
- GatewayModifyListeners
result: failure
statistics:
Failed: 4
Passed: 8
Skipped: 0
name: GATEWAY-GRPC
summary: Core tests failed with 4 test failures.
- core:
failedTests:
- GatewayModifyListeners
result: failure
skippedTests:
- HTTPRouteHTTPSListener
statistics:
Failed: 1
Passed: 31
Skipped: 1
extended:
failedTests:
- HTTPRouteBackendProtocolWebSocket
result: failure
skippedTests:
- HTTPRouteRedirectPortAndScheme
statistics:
Failed: 1
Passed: 10
Skipped: 1
supportedFeatures:
- GatewayAddressEmpty
- GatewayPort8080
- HTTPRouteBackendProtocolWebSocket
- HTTPRouteDestinationPortMatching
- HTTPRouteHostRewrite
- HTTPRouteMethodMatching
- HTTPRoutePathRewrite
- HTTPRoutePortRedirect
- HTTPRouteQueryParamMatching
- HTTPRouteRequestMirror
- HTTPRouteResponseHeaderModification
- HTTPRouteSchemeRedirect
unsupportedFeatures:
- GatewayHTTPListenerIsolation
- GatewayInfrastructurePropagation
- GatewayStaticAddresses
- HTTPRouteBackendProtocolH2C
- HTTPRouteBackendRequestHeaderModification
- HTTPRouteBackendTimeout
- HTTPRouteParentRefPort
- HTTPRoutePathRedirect
- HTTPRouteRequestMultipleMirrors
- HTTPRouteRequestPercentageMirror
- HTTPRouteRequestTimeout
name: GATEWAY-HTTP
summary: Core tests failed with 1 test failures. Extended tests failed with 1 test
failures.
- core:
failedTests:
- GatewayModifyListeners
- TLSRouteSimpleSameNamespace
result: failure
statistics:
Failed: 2
Passed: 9
Skipped: 0
name: GATEWAY-TLS
summary: Core tests failed with 2 test failures. |
Summary
Add
Bodyas a new scope value forApisixRouteHTTPMatchExprSubject, enabling request body matching inApisixRouteHTTP match expressions.How it works
When
scope: Bodyis used, the subject maps to APISIX'spost_arg.<name>variable. This variable supports:application/jsonapplication/x-www-form-urlencodedmultipart/form-dataDot-notation JSON path expressions are also supported (e.g.,
model.version,messages[*].role).Example:
Changes
api/v2/shared_types.go: addScopeBody = "Body"constantapi/v2/apisixroute_types.go:case ScopeBodyinToVars()mapping topost_arg.<name>Bodyto+kubebuilder:validation:EnumonScopefield+kubebuilder:validation:XValidationCEL rule:nameis required whenscopeis notPathNamefield optional (omitempty) soPathscope works without providing a nameapi/v2/apisixroute_types_test.go: unit tests for Body scope and CEL validationconfig/crd/bases/apisix.apache.org_apisixroutes.yaml: regenerateddocs/en/latest/reference/api-reference.md: regeneratedtest/e2e/crds/v2/route.go: e2e tests for urlencoded form field and JSON nested path matchingTesting
Unit tests:
E2e tests added:
Test ApisixRoute match by body vars (urlencoded): POST form fieldaction=loginTest ApisixRoute match by body vars (JSON nested path): POST JSON{"model": {"version": "gpt-4"}}withmodel.versiondot-notationCloses: #399