router: fix a bug where internal redirect will hang up request or unexpected redirect#44154
router: fix a bug where internal redirect will hang up request or unexpected redirect#44154wbpcode merged 4 commits intoenvoyproxy:mainfrom
Conversation
Signed-off-by: wbpcode/wangbaiping <wbphub@gmail.com>
Signed-off-by: wbpcode/wangbaiping <wbphub@gmail.com>
Signed-off-by: wbpcode/wangbaiping <wbphub@gmail.com>
|
This at least need to be back ported to 1.36 and 1.37. |
| if (downstream_end_stream_ && (!request_buffer_overflowed_ || !callbacks_->decodingBuffer()) && | ||
| location != nullptr && | ||
| if (downstream_end_stream_ && (!request_buffer_overflowed_) && location != nullptr && |
There was a problem hiding this comment.
The !request_buffer_overflowed_ || !callbacks_->decodingBuffer() will result in unexpected redirection because it's possible the the request has body but first chunk overflow and the decodingBuffer() still be nullptr.
| // Check if buffer overflow occurred and override error details accordingly | ||
| if (request_buffer_overflowed_) { | ||
| code = Http::Code::InsufficientStorage; | ||
| body = "exceeded request buffer limit while retrying upstream"; | ||
| details = StreamInfo::ResponseCodeDetails::get().RequestPayloadExceededRetryBufferLimit; | ||
| } |
There was a problem hiding this comment.
The buffer overflow will affect retry and redirection. But if upstream abort (reset, connection failure), we should expose the actual error from upstream to client. This is also introduced at #40254
| EXPECT_CALL(callbacks_.route_->route_entry_, requestBodyBufferLimit()).WillOnce(Return(10)); | ||
|
|
||
| NiceMock<Http::MockRequestEncoder> encoder1; | ||
| Http::ResponseDecoder* response_decoder = nullptr; | ||
| expectNewStreamWithImmediateEncoder(encoder1, &response_decoder, Http::Protocol::Http10); | ||
|
|
||
| Http::TestRequestHeaderMapImpl headers{ | ||
| {"x-envoy-retry-on", "5xx"}, {"x-envoy-internal", "true"}, {"myheader", "present"}}; | ||
| HttpTestUtility::addDefaultHeaders(headers); | ||
| router_->decodeHeaders(headers, false); |
There was a problem hiding this comment.
This PR also removed some repeated tests for buffer/retry.
|
/retest |
agrawroh
left a comment
There was a problem hiding this comment.
LGTM, Thank You for fixing it.
|
|
||
| // In production, the HCM recreateStream would have called this. | ||
| router_->onDestroy(); | ||
| EXPECT_FALSE(callbacks_.streamInfo().filterState()->hasDataWithName("num_internal_redirects")); |
There was a problem hiding this comment.
Should we also verify that retry_or_shadow_abandoned gets incremented as we would increment that now per the new flow?
EXPECT_EQ(1U, cm_.thread_local_cluster_.cluster_.info_->stats_store_.counter("retry_or_shadow_abandoned").value());
EXPECT_EQ(1U, cm_.thread_local_cluster_.cluster_.info_->stats_store_.counter("upstream_internal_redirect_failed_total").value());| // request. | ||
| if (would_exceed_buffer && retry_enabled && !is_redirect_only && !request_buffer_overflowed_) { | ||
| // Handle buffer overflow. | ||
| if (buffering && would_exceed_buffer && !request_buffer_overflowed_) { |
There was a problem hiding this comment.
I think we could just remove !request_buffer_overflowed_ from here as it's already covered as part of buffering?
| Http::ResponseDecoder* response_decoder = nullptr; | ||
| expectNewStreamWithImmediateEncoder(encoder1, &response_decoder, Http::Protocol::Http10); | ||
|
|
||
| // Enable redirects also. This feature will not be used but will affects buffer logic. |
There was a problem hiding this comment.
| // Enable redirects also. This feature will not be used but will affects buffer logic. | |
| // Enable redirects also. This feature will not be used but will affect buffer logic. |
| Buffer::OwnedImpl body("t"); | ||
| router_->decodeData(body, false); | ||
| Buffer::OwnedImpl body2("t"); | ||
| // Ensure the second chunk also isn't buffered and triggers the retry logic again. |
There was a problem hiding this comment.
| // Ensure the second chunk also isn't buffered and triggers the retry logic again. | |
| // Ensure the second chunk also isn't buffered and triggers the retry logic again. | |
| // Ensure subsequent chunks after overflow are also not buffered. |
Signed-off-by: wbpcode/wangbaiping <wbphub@gmail.com>
|
gently ping @yanavlasov |
|
Hah, I found @yanavlasov recently no activity on github. Let me ping @ggreenway |
|
/backport |
…xpected redirect (envoyproxy#44154) Signed-off-by: wbpcode <wbphub@gmail.com>
…xpected redirect (envoyproxy#44154) Signed-off-by: wbpcode <wbphub@gmail.com>
…xpected redirect (#44154) (#44304) Commit Message: router: fix a bug where internal redirect will hang up request or unexpected redirect (#44154) Additional Description: Risk Level: Testing: Docs Changes: Release Notes: Platform Specific Features: [Optional Runtime guard:] [Optional Fixes #Issue] [Optional Fixes commit #PR or SHA] [Optional Deprecated:] [Optional [API Considerations](https://github.com/envoyproxy/envoy/blob/main/api/review_checklist.md):] Signed-off-by: wbpcode <wbphub@gmail.com>
…xpected redirect (#44154) (#44303) Commit Message: router: fix a bug where internal redirect will hang up request or unexpected redirect (#44154) Additional Description: Risk Level: Testing: Docs Changes: Release Notes: Platform Specific Features: [Optional Runtime guard:] [Optional Fixes #Issue] [Optional Fixes commit #PR or SHA] [Optional Deprecated:] [Optional [API Considerations](https://github.com/envoyproxy/envoy/blob/main/api/review_checklist.md):] Signed-off-by: wbpcode <wbphub@gmail.com>
…xpected redirect (envoyproxy#44154) Signed-off-by: Nick Shipilov <nick.shipilov.n@gmail.com>
Commit Message: router: fix a bug where internal redirect will hang up request or unexpected redirect
Additional Description:
To close #44114
The PR fixed some bugs that introduced in the #40254 and also other old bug existed for a while.
In previous implementation:
decodingBuffer()will always return nullptr. This will finally result in unexpected redirection becausedecodingBuffer() == nullptrbe used as a flag that could redirect.bufferingflag is not set correctly) and will hang up the request (because the readDisable(true) and TCP flow control) if the buffer is overflowed and the request is still not completed.bufferingflag will be false, so chunk X will be skipped correctly.bufferingflag will not be set correctly and result in problem.Risk Level: mid, core logic change.
Testing: unit.
Docs Changes: n/a.
Release Notes: added.
Platform Specific Features: n/a.