Skip to content

[bbr] Skip body re-serialization when unchanged#2556

Merged
k8s-ci-robot merged 1 commit intokubernetes-sigs:mainfrom
asaadbalum:skip-request-body-remarshal
Mar 12, 2026
Merged

[bbr] Skip body re-serialization when unchanged#2556
k8s-ci-robot merged 1 commit intokubernetes-sigs:mainfrom
asaadbalum:skip-request-body-remarshal

Conversation

@asaadbalum
Copy link
Copy Markdown
Contributor

@asaadbalum asaadbalum commented Mar 12, 2026

Summary

  • Add body mutation tracking to InferenceMessage via SetBody, SetBodyField, RemoveBodyField, and BodyMutated so the request and response handlers skip json.Marshal and Content-Length update when no plugin modified the body
  • Apply the optimization to both request (request.go) and response (response.go) paths: for unary, omit BodyMutation when unchanged; for streaming, forward original bytes when unchanged
  • Add integration tests that verify body mutation tracking over real gRPC for both unary and streaming paths

This is a follow-up to #2551, which added request body mutation support but always re-marshaled regardless of whether plugins modified the body.

What type of PR is this?

/kind feature

What's changed:

Path Change
pkg/bbr/framework/types.go Add bodyMutated flag; SetBody replaces entire body; SetBodyField/RemoveBodyField for field-level mutations; BodyMutated accessor
pkg/bbr/framework/types_test.go Unit tests for body mutation tracking API (SetBody, SetBodyField, RemoveBodyField, BodyMutated)
pkg/bbr/handlers/request.go Conditionally marshal/include BodyMutation only when body changed
pkg/bbr/handlers/response.go Same conditional logic for response path
pkg/bbr/handlers/request_test.go Body mutation tests (unary + streaming)
pkg/bbr/handlers/response_test.go Body mutation + no-mutation tests (unary + streaming)
pkg/bbr/handlers/server_test.go Remove stale Content-Length/BodyMutation expectations
test/integration/bbr/harness.go Add NewBBRHarnessWithPlugins for custom plugin injection
test/integration/bbr/body_mutation_test.go Integration tests: body-mutating plugin over real gRPC (unary + streaming)
test/integration/bbr/util.go Remove stale expectations, clean unused prompt parameter
test/integration/bbr/hermetic_test.go Update call sites for cleaned function signatures

Does this PR introduce a user-facing change?

Users writing BBR plugins that do NOT modify the request/response body will see reduced overhead — no unnecessary JSON marshaling or Content-Length rewriting. Plugins that modify the body should use SetBody (full replacement), SetBodyField, or RemoveBodyField to ensure the dirty flag is set.

@k8s-ci-robot k8s-ci-robot added the kind/feature Categorizes issue or PR as related to a new feature. label Mar 12, 2026
@netlify
Copy link
Copy Markdown

netlify Bot commented Mar 12, 2026

Deploy Preview for gateway-api-inference-extension ready!

Name Link
🔨 Latest commit b60e5b8
🔍 Latest deploy log https://app.netlify.com/projects/gateway-api-inference-extension/deploys/69b2e9f52ca9b80008181df8
😎 Deploy Preview https://deploy-preview-2556--gateway-api-inference-extension.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@k8s-ci-robot k8s-ci-robot added cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test. labels Mar 12, 2026
@k8s-ci-robot
Copy link
Copy Markdown
Contributor

Hi @asaadbalum. Thanks for your PR.

I'm waiting for a kubernetes-sigs member to verify that this patch is reasonable to test. If it is, they should reply with /ok-to-test on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work.

Tip

We noticed you've done this a few times! Consider joining the org to skip this step and gain /lgtm and other bot rights. We recommend asking approvers on your previous PRs to sponsor you.

Once the patch is verified, the new status will be reflected by the ok-to-test label.

I understand the commands that are listed here.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

@k8s-ci-robot k8s-ci-robot added the size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. label Mar 12, 2026
@asaadbalum asaadbalum marked this pull request as draft March 12, 2026 11:46
@k8s-ci-robot k8s-ci-robot added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Mar 12, 2026
@asaadbalum asaadbalum force-pushed the skip-request-body-remarshal branch 2 times, most recently from 5ae56cc to bea9ce8 Compare March 12, 2026 12:06
@asaadbalum asaadbalum marked this pull request as ready for review March 12, 2026 12:06
@k8s-ci-robot k8s-ci-robot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Mar 12, 2026
@k8s-ci-robot k8s-ci-robot requested a review from kfswain March 12, 2026 12:07
@asaadbalum asaadbalum force-pushed the skip-request-body-remarshal branch from bea9ce8 to 0be4cf4 Compare March 12, 2026 12:09
Copy link
Copy Markdown
Contributor

@nirrozenbaum nirrozenbaum left a comment

Choose a reason for hiding this comment

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

overall lgtm
left few minor nits

Comment thread pkg/bbr/framework/types.go Outdated
}
}

func (r *InferenceMessage) BodyWasMutated() bool {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nit: rename to BodyMutated()

Suggested change
func (r *InferenceMessage) BodyWasMutated() bool {
func (r *InferenceMessage) BodyMutated() bool {

Comment thread pkg/bbr/handlers/request.go Outdated
}

// Necessary so that the new headers are used in the routing decision.
resp := &eppb.CommonResponse{
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nit: can we call response?

Comment thread pkg/bbr/handlers/request.go Outdated
bodyMutated := reqCtx.Request.BodyWasMutated()
var mutatedBodyBytes []byte
if bodyMutated {
b, err := json.Marshal(reqCtx.Request.Body)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

why do we need b? can't we marshal directly to mutatedBodyBytes?

Comment thread pkg/bbr/handlers/response.go Outdated
bodyMutated := reqCtx.Response.BodyWasMutated()
var mutatedBytes []byte
if bodyMutated {
b, err := json.Marshal(reqCtx.Response.Body)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

ditto

Comment thread pkg/bbr/handlers/response.go Outdated
return ret, nil
}

resp := &eppb.CommonResponse{
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

ditto

@asaadbalum asaadbalum force-pushed the skip-request-body-remarshal branch from 0be4cf4 to b106e2b Compare March 12, 2026 14:06
@nirrozenbaum
Copy link
Copy Markdown
Contributor

/ok-to-test

@k8s-ci-robot k8s-ci-robot added ok-to-test Indicates a non-member PR verified by an org member that is safe to test. and removed needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test. labels Mar 12, 2026
r.bodyMutated = true
}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think we need here additional function to set the whole body.
something like:

func (r *InferenceMessage) SetBody(body map[string]any) {
   r.Body = body
   r.bodyMutated = true
}

this might be useful for plugins that transform the body in some way (e.g., api translation from OpenAI to Anthropic) and want to set the whole body at once.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Agree, sending a patch in a min

Add body mutation tracking to InferenceMessage via SetBody,
SetBodyField, RemoveBodyField, and BodyMutated so the request and
response handlers skip json.Marshal and Content-Length update when
no plugin modified the body.

SetBody replaces the entire body map for plugins that transform the
full payload (e.g., API translation). SetBodyField and RemoveBodyField
handle granular field-level mutations.

For unary mode, omit BodyMutation from the ext_proc response when
unchanged. For streaming mode, forward original bytes instead of
re-marshaling.

Add integration tests that verify body mutation tracking over real
gRPC for both unary and streaming paths.

Signed-off-by: Asaad Balum <asaad.balum@gmail.com>
@asaadbalum asaadbalum force-pushed the skip-request-body-remarshal branch from b106e2b to b60e5b8 Compare March 12, 2026 16:29
Copy link
Copy Markdown
Contributor

@nirrozenbaum nirrozenbaum left a comment

Choose a reason for hiding this comment

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

/lgtm
/approve

Thanks!

@k8s-ci-robot k8s-ci-robot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Mar 12, 2026
@k8s-ci-robot
Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: asaadbalum, nirrozenbaum

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@k8s-ci-robot k8s-ci-robot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Mar 12, 2026
@asaadbalum
Copy link
Copy Markdown
Contributor Author

/test pull-gateway-api-inference-extension-test-e2e-main

@k8s-ci-robot k8s-ci-robot merged commit 0ff1d13 into kubernetes-sigs:main Mar 12, 2026
11 checks passed
@asaadbalum asaadbalum deleted the skip-request-body-remarshal branch March 12, 2026 23:08
BizerNotNull pushed a commit to BizerNotNull/gateway-api-inference-extension that referenced this pull request Mar 15, 2026
…tes-sigs#2556)

Add body mutation tracking to InferenceMessage via SetBody,
SetBodyField, RemoveBodyField, and BodyMutated so the request and
response handlers skip json.Marshal and Content-Length update when
no plugin modified the body.

SetBody replaces the entire body map for plugins that transform the
full payload (e.g., API translation). SetBodyField and RemoveBodyField
handle granular field-level mutations.

For unary mode, omit BodyMutation from the ext_proc response when
unchanged. For streaming mode, forward original bytes instead of
re-marshaling.

Add integration tests that verify body mutation tracking over real
gRPC for both unary and streaming paths.

Signed-off-by: Asaad Balum <asaad.balum@gmail.com>
nirrozenbaum pushed a commit to llm-d/llm-d-inference-payload-processor that referenced this pull request Apr 28, 2026
…tes-sigs/gateway-api-inference-extension#2556)

Add body mutation tracking to InferenceMessage via SetBody,
SetBodyField, RemoveBodyField, and BodyMutated so the request and
response handlers skip json.Marshal and Content-Length update when
no plugin modified the body.

SetBody replaces the entire body map for plugins that transform the
full payload (e.g., API translation). SetBodyField and RemoveBodyField
handle granular field-level mutations.

For unary mode, omit BodyMutation from the ext_proc response when
unchanged. For streaming mode, forward original bytes instead of
re-marshaling.

Add integration tests that verify body mutation tracking over real
gRPC for both unary and streaming paths.

Signed-off-by: Asaad Balum <asaad.balum@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. kind/feature Categorizes issue or PR as related to a new feature. lgtm "Looks good to me", indicates that a PR is ready to be merged. ok-to-test Indicates a non-member PR verified by an org member that is safe to test. size/XL Denotes a PR that changes 500-999 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants