Skip to content

feat: support Body scope in ApisixRoute HTTP match expressions#415

Open
AlinsRan wants to merge 1 commit into
masterfrom
feat/body-scope-matching-v2
Open

feat: support Body scope in ApisixRoute HTTP match expressions#415
AlinsRan wants to merge 1 commit into
masterfrom
feat/body-scope-matching-v2

Conversation

@AlinsRan
Copy link
Copy Markdown
Contributor

@AlinsRan AlinsRan commented May 12, 2026

Summary

Add Body as a new scope value for ApisixRouteHTTPMatchExprSubject, enabling request body matching in ApisixRoute HTTP match expressions.

How it works

When scope: Body is used, the subject maps to APISIX's post_arg.<name> variable. This variable supports:

  • application/json
  • application/x-www-form-urlencoded
  • multipart/form-data

Dot-notation JSON path expressions are also supported (e.g., model.version, messages[*].role).

Example:

exprs:
- subject:
    scope: Body
    name: action        # matches form field or JSON key
  op: Equal
  value: login
exprs:
- subject:
    scope: Body
    name: model.version  # dot-notation JSON path
  op: Equal
  value: gpt-4

Changes

  • api/v2/shared_types.go: add ScopeBody = "Body" constant
  • api/v2/apisixroute_types.go:
    • Add case ScopeBody in ToVars() mapping to post_arg.<name>
    • Add Body to +kubebuilder:validation:Enum on Scope field
    • Add +kubebuilder:validation:XValidation CEL rule: name is required when scope is not Path
    • Make Name field optional (omitempty) so Path scope works without providing a name
  • api/v2/apisixroute_types_test.go: unit tests for Body scope and CEL validation
  • config/crd/bases/apisix.apache.org_apisixroutes.yaml: regenerated
  • docs/en/latest/reference/api-reference.md: regenerated
  • test/e2e/crds/v2/route.go: e2e tests for urlencoded form field and JSON nested path matching

Testing

Unit tests:

go test ./api/v2/... -run "TestToVars|TestCEL"

E2e tests added:

  • Test ApisixRoute match by body vars (urlencoded): POST form field action=login
  • Test ApisixRoute match by body vars (JSON nested path): POST JSON {"model": {"version": "gpt-4"}} with model.version dot-notation

Closes: #399

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
Copilot AI review requested due to automatic review settings May 12, 2026 06:26
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 12, 2026

📝 Walkthrough

Walkthrough

This PR introduces request body field matching capability for ApisixRoute HTTP match expressions. The core addition is a new Body scope that enables matching against request body fields using dot-notation JSON paths, mapping to APISIX's post_arg.<name> variable. The feature is validated through CEL rules, comprehensive test coverage, and updated documentation.

Changes

Body Scope Feature

Layer / File(s) Summary
Scope Constant and Type Definition
api/v2/shared_types.go, api/v2/apisixroute_types.go
Added ScopeBody constant with documentation for JSON path support and post_arg.<name> mapping. Updated ApisixRouteHTTPMatchExprSubject struct with expanded scope enum, XValidation rule requiring name for non-Path scopes, optional name field, and added Body case handling in ToVars() mapping to post_arg variables.
CRD Schema Definition
config/crd/bases/apisix.apache.org_apisixroutes.yaml
Expanded OpenAPI schema for HTTP match subject with Body and Variable scope values, added XValidation rule enforcing name presence for non-Path scopes, and removed API7 Enterprise compatibility note from filter_func description.
CRD Schema Validation Test Helper
api/v2/crd_schema_validator_test.go
Introduced crdSchemaValidator test utility performing OpenAPI structural validation and CEL rule checking; added loadCRDSchema helper to read CRD YAML, extract v2 schema, build structural schema, and instantiate validator for reusable schema validation testing.
Body Scope Test Coverage
api/v2/apisixroute_types_test.go
Added four test cases validating Body scope: simple field names pass validation, nested JSON path notation passes, empty name fails with required message, and Path scope allows empty name; includes helper functions for route construction and typed literal pointers.
API Reference Documentation
docs/en/latest/reference/api-reference.md
Expanded documentation for ApisixRouteHTTPMatchExprSubject with Body scope details, dot-notation JSON path support, post_arg mapping, and clarified when name is optional; updated variable documentation links and removed product-specific compatibility notes.
Test Refactoring: Shared Schema Validator
api/v2/apisixconsumer_validation_test.go
Refactored to remove local schema-validation implementation and delegate to shared loadCRDSchema helper; simplified imports and reduced code duplication across test files.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related issues

  • api7/api7-ingress-controller#399: This PR directly implements the request-body matching enhancement by adding Body scope, updating validation rules, mapping to APISIX post_arg variables, and adding comprehensive test coverage.

Possibly related PRs

  • api7/api7-ingress-controller#406: This PR refactors the consumer validation test to use the shared crdSchemaValidator helper introduced in this change, replacing a consumer-specific schema validator.

Suggested reviewers

  • shreemaan-abhishek
🚥 Pre-merge checks | ✅ 5 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
E2e Test Quality Review ⚠️ Warning E2E test coverage for Body scope feature is completely missing. Only unit/schema validation tests exist. No integration tests verify the actual end-to-end request matching behavior in APISIX. Add E2E tests in test/e2e/crds/v2/route.go verifying Body scope matching with actual HTTP requests against APISIX. Current tests only validate CRD schema structure, not runtime behavior of post_arg. variable matching.
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The PR title accurately summarizes the main change: adding Body scope support to ApisixRoute HTTP match expressions, which aligns with the core modifications across shared_types.go, apisixroute_types.go, tests, CRD manifests, and documentation.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Security Check ✅ Passed No security vulnerabilities found. PR adds Body scope support with proper validation, no sensitive data exposure in logs/tests, no auth/crypto/database issues detected.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/body-scope-matching-v2

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 ScopeBody and map Body scope in ApisixRouteHTTPMatchExprs.ToVars() to post_arg.<name>.
  • Update ApisixRouteHTTPMatchExprSubject CRD schema: expand enum (incl. Body), make name optional for Path, and enforce name via CEL validation for non-Path scopes.
  • 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.

Comment thread config/crd/bases/apisix.apache.org_apisixroutes.yaml
Comment thread api/v2/apisixroute_types.go
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
api/v2/apisixconsumer_validation_test.go (1)

29-35: LGTM!

Good refactoring that eliminates code duplication by delegating to the shared loadCRDSchema helper. The path construction using runtime.Caller and filepath.Join is 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

📥 Commits

Reviewing files that changed from the base of the PR and between 0283a04 and 334db60.

📒 Files selected for processing (7)
  • api/v2/apisixconsumer_validation_test.go
  • api/v2/apisixroute_types.go
  • api/v2/apisixroute_types_test.go
  • api/v2/crd_schema_validator_test.go
  • api/v2/shared_types.go
  • config/crd/bases/apisix.apache.org_apisixroutes.yaml
  • docs/en/latest/reference/api-reference.md

@github-actions
Copy link
Copy Markdown
Contributor

conformance test report - apisix mode

apiVersion: 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.

@github-actions
Copy link
Copy Markdown
Contributor

conformance test report - apisix-standalone mode

apiVersion: 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.

@github-actions
Copy link
Copy Markdown
Contributor

conformance test report

apiVersion: 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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

enhancement: support request body matching in Gateway API and ApisixRoute

3 participants