Skip to content

fix: duplicate request body when when using FULL_DUPLEX_STREAMED ext_proc body mode with retries enabled#46095

Open
yuehaii wants to merge 2 commits into
envoyproxy:mainfrom
yuehaii:envoy-dup-body-extproc
Open

fix: duplicate request body when when using FULL_DUPLEX_STREAMED ext_proc body mode with retries enabled#46095
yuehaii wants to merge 2 commits into
envoyproxy:mainfrom
yuehaii:envoy-dup-body-extproc

Conversation

@yuehaii

@yuehaii yuehaii commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

Commit Message:
when the ExtProc HTTP filter is configured with requestBodyProcessingMode: FULL_DUPLEX_STREAMED and the router has retries enabled, the upstream receives the request body twice. once from the normal ext_proc forwarding path, and once replayed from the router's retry buffer.

Additional Description:
the flag skip_body_on_next_continue_ is added to ActiveStreamDecoderFilter. when set, bufferedData() returns a null pointer which causing doData() to be skipped. the router's retry buffer buffered_request_data_ is never modified, so retry correctness is preserved.

Risk Level:
Low

Testing:

==================== Test output for //test/extensions/filters/http/ext_proc:filter_full_duplex_test:
Note: Google Test filter = HttpFilterTest.FullDuplexStreamedNoBodyDuplicationOnRetryBuffer:HttpFilterTest.FullDuplexStreamedNoBodyDuplicationOnRetryBufferNoTrailers
[==========] Running 2 tests from 1 test suite.
[----------] Global test environment set-up.
[----------] 2 tests from HttpFilterTest
[ RUN ] HttpFilterTest.FullDuplexStreamedNoBodyDuplicationOnRetryBuffer
[external/abseil-cpp/absl/flags/internal/flag.cc : 148] RAW: Restore saved value of envoy_quic_always_support_server_preferred_address to: true
[external/abseil-cpp/absl/flags/internal/flag.cc : 148] RAW: Restore saved value of envoy_reloadable_features_ext_proc_inject_data_with_state_update to: true
[external/abseil-cpp/absl/flags/internal/flag.cc : 148] RAW: Restore saved value of envoy_reloadable_features_ext_proc_return_stop_iteration to: true
[external/abseil-cpp/absl/flags/internal/flag.cc : 148] RAW: Restore saved value of envoy_reloadable_features_ext_proc_stream_close_optimization to: true
[external/abseil-cpp/absl/flags/internal/flag.cc : 148] RAW: Restore saved value of envoy_reloadable_features_runtime_initialized to: false
[external/abseil-cpp/absl/flags/internal/flag.cc : 148] RAW: Restore saved value of envoy_quic_always_support_server_preferred_address to: true
[external/abseil-cpp/absl/flags/internal/flag.cc : 148] RAW: Restore saved value of envoy_reloadable_features_ext_proc_inject_data_with_state_update to: true
[external/abseil-cpp/absl/flags/internal/flag.cc : 148] RAW: Restore saved value of envoy_reloadable_features_ext_proc_return_stop_iteration to: true
[external/abseil-cpp/absl/flags/internal/flag.cc : 148] RAW: Restore saved value of envoy_reloadable_features_ext_proc_stream_close_optimization to: true
[external/abseil-cpp/absl/flags/internal/flag.cc : 148] RAW: Restore saved value of envoy_reloadable_features_runtime_initialized to: false
[external/abseil-cpp/absl/flags/internal/flag.cc : 148] RAW: Restore saved value of envoy_quic_always_support_server_preferred_address to: true
[external/abseil-cpp/absl/flags/internal/flag.cc : 148] RAW: Restore saved value of envoy_reloadable_features_ext_proc_inject_data_with_state_update to: true
[external/abseil-cpp/absl/flags/internal/flag.cc : 148] RAW: Restore saved value of envoy_reloadable_features_ext_proc_return_stop_iteration to: true
[external/abseil-cpp/absl/flags/internal/flag.cc : 148] RAW: Restore saved value of envoy_reloadable_features_ext_proc_stream_close_optimization to: true
[external/abseil-cpp/absl/flags/internal/flag.cc : 148] RAW: Restore saved value of envoy_reloadable_features_runtime_initialized to: false
[ OK ] HttpFilterTest.FullDuplexStreamedNoBodyDuplicationOnRetryBuffer (79 ms)
[ RUN ] HttpFilterTest.FullDuplexStreamedNoBodyDuplicationOnRetryBufferNoTrailers
[external/abseil-cpp/absl/flags/internal/flag.cc : 148] RAW: Restore saved value of envoy_quic_always_support_server_preferred_address to: true
[external/abseil-cpp/absl/flags/internal/flag.cc : 148] RAW: Restore saved value of envoy_reloadable_features_ext_proc_inject_data_with_state_update to: true
[external/abseil-cpp/absl/flags/internal/flag.cc : 148] RAW: Restore saved value of envoy_reloadable_features_ext_proc_return_stop_iteration to: true
[external/abseil-cpp/absl/flags/internal/flag.cc : 148] RAW: Restore saved value of envoy_reloadable_features_ext_proc_stream_close_optimization to: true
[external/abseil-cpp/absl/flags/internal/flag.cc : 148] RAW: Restore saved value of envoy_reloadable_features_runtime_initialized to: false
[external/abseil-cpp/absl/flags/internal/flag.cc : 148] RAW: Restore saved value of envoy_quic_always_support_server_preferred_address to: true
[external/abseil-cpp/absl/flags/internal/flag.cc : 148] RAW: Restore saved value of envoy_reloadable_features_ext_proc_inject_data_with_state_update to: true
[external/abseil-cpp/absl/flags/internal/flag.cc : 148] RAW: Restore saved value of envoy_reloadable_features_ext_proc_return_stop_iteration to: true
[external/abseil-cpp/absl/flags/internal/flag.cc : 148] RAW: Restore saved value of envoy_reloadable_features_ext_proc_stream_close_optimization to: true
[external/abseil-cpp/absl/flags/internal/flag.cc : 148] RAW: Restore saved value of envoy_reloadable_features_runtime_initialized to: false
[external/abseil-cpp/absl/flags/internal/flag.cc : 148] RAW: Restore saved value of envoy_quic_always_support_server_preferred_address to: true
[external/abseil-cpp/absl/flags/internal/flag.cc : 148] RAW: Restore saved value of envoy_reloadable_features_ext_proc_inject_data_with_state_update to: true
[external/abseil-cpp/absl/flags/internal/flag.cc : 148] RAW: Restore saved value of envoy_reloadable_features_ext_proc_return_stop_iteration to: true
[external/abseil-cpp/absl/flags/internal/flag.cc : 148] RAW: Restore saved value of envoy_reloadable_features_ext_proc_stream_close_optimization to: true
[external/abseil-cpp/absl/flags/internal/flag.cc : 148] RAW: Restore saved value of envoy_reloadable_features_runtime_initialized to: false
[ OK ] HttpFilterTest.FullDuplexStreamedNoBodyDuplicationOnRetryBufferNoTrailers (60 ms)
[----------] 2 tests from HttpFilterTest (140 ms total)

[----------] Global test environment tear-down
[==========] 2 tests from 1 test suite ran. (140 ms total)
[ PASSED ] 2 tests.

Release Notes:
fix request body duplicated at upstream when using FULL_DUPLEX_STREAMED ext_proc body mode with retries enabled

Fixes #45470

…roc body mode with retries enabled.

Signed-off-by: hai.yue <20416005+yuehaii@users.noreply.github.com>
Signed-off-by: hai.yue <20416005+yuehaii@users.noreply.github.com>
@gemini-code-assist

Copy link
Copy Markdown
Contributor

I apologize, but I do not have the capability to trigger a retest of the pull request. As an AI assistant, I can only provide code reviews and summaries. To trigger a retest, please check your CI/CD platform's documentation or use the specific command provided by your repository's CI system.

@yuehaii

yuehaii commented Jul 14, 2026

Copy link
Copy Markdown
Contributor Author

/retest

@tyxia

tyxia commented Jul 14, 2026

Copy link
Copy Markdown
Member

@yanjunxiang-google PTAL as well when you have time.

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.

Body duplication when using the ExtProc filter and enabling retry policy

3 participants