HTTPCLIENT-2433: Prevent concurrent HTTP/2 request body replay - #884
Conversation
|
@mkurz The test coverage looks awesome! However I need a little while to digest the proposed fix. Please bear with me. |
There was a problem hiding this comment.
@mkurz Your suggested fix is perfectly fine.
For the sake of code consistency could we use the same approach as used in HttpAsyncMainClientExec using AtomicInteger instead of two AtomicBoolean?
Wait for both sides of an HTTP/2 exchange to terminate before completing it, including graceful request termination after RST_STREAM(NO_ERROR). Cover authentication replay with a large file and with a body-less 401 followed by a graceful stream reset.
17cf048 to
8483a2a
Compare
|
@ok2c done! |
|
Cherry-picked to |
|
@mkurz Many thanks for reporting the problem and contributing the fix |
|
@ok2c thanks for merging them ;) |
|
@ok2c do you have an eta when next core and client patch release will be cut? |
|
@mkurz Soon. I will try to cut the core releases this weekend. The client bug I see as less severe as it affects H2 only client, so it may take a bit longer. |
|
@mkurz I made some major simplifications to the main async exec interceptor code with 4a72958. Please do feel free to double-check. If you confirm the change-set does not break anything on your end, I will cherry-pick it to |
|
I tested the simplification on master and cherry-picked it cleanly onto the current Looks good to me @ok2c, thanks! |
|
Thanks @mkurz Much appreciated. |
This fixes HTTPCLIENT-2433.
When an HTTP/2 authentication challenge completed before the request body had finished,
H2AsyncMainClientExecpreviously notified the execution chain that the exchange was complete immediately. The authentication handler could then release and reuse the same repeatable entity producer while the original HTTP/2 stream was still consuming it, corrupting the replayed request body.The HTTP/2 execution handler now completes the exchange only after both request output and response input have terminated. It also handles a graceful
RST_STREAM(NO_ERROR)after a complete response as request-side termination, allowing authentication replay to continue without hanging.Regression coverage includes:
401followed byRST_STREAM(NO_ERROR), verifying that the authenticated retry completes with the exact 2 MB request body.Reproducer:
https://github.com/mkurz/apache-httpclient5-h2-auth-replay-reproducer
Tests: