On Tue, 11 Nov 2025 11:31:22 GMT, EunHyunsu <[email protected]> wrote:
> ### Summary
> This patch addresses the issue where `HttpResponse.body()` returns `null`
> for 407 responses when using HTTPS through a proxy, while HTTP requests
> correctly return the response body.
>
> ### Problem
> When an HTTPS request receives a 407 Proxy Authentication Required
> response, the response body is discarded during CONNECT tunnel establishment.
> This is inconsistent with HTTP behavior where the body is properly returned.
>
> **Root cause:**
> - HTTPS uses `MultiExchange<Void>` for CONNECT requests
> - The body is explicitly ignored via `ignoreBody()` on 407 responses
> - No mechanism exists to preserve the body for later retrieval
>
> ### Proposed Solution
> I propose the following changes to preserve and return the 407 response
> body:
>
> 1. **PlainTunnelingConnection.java**: Change `MultiExchange<Void>` to
> `MultiExchange<byte[]>` and read the body on 407 responses instead of
> ignoring it
>
> 2. **ProxyAuthenticationRequired.java**: Add `proxyResponseBody` field to
> carry the body bytes through the exception
>
> 3. **Exchange.java**: Cache both the proxy response and body, then return
> them when the application calls `body()`
>
> ### Testing
> Added comprehensive test (`ProxyAuthHttpTest.java`) covering:
> - Basic HTTP and HTTPS 407 responses
> - Multiple `BodyHandler` types: `ofString()`, `ofByteArray()`,
> `ofInputStream()`, `ofLines()`
> - Response headers validation
>
> **Test results**: 38/38 passed
>
> ### Notes
> - This change only affects 407 responses; all other flows remain unchanged
> - The cached body is cleared after first use to prevent reuse
> - No changes to public APIs; internal implementation only
>
> I'd appreciate any feedback on this approach. If there's a better way to
> handle this, I'm happy to revise.
@dfuchs Thank you for the detailed feedback!
You're absolutely right about the memory concerns with forced byte[]
conversion.
I noticed that `Http1Response.ignoreBody()` uses a similar pattern with
`MAX_IGNORE = 1024` for handling redirect response bodies. We could apply a
comparable approach here:
private static final int MAX_PROXY_ERROR_BODY = 8192; // or 16384
if (resp.statusCode() == 407) {
long contentLength = resp.headers()
.firstValueAsLong("Content-Length").orElse(-1);
if (contentLength >= 0 && contentLength <= MAX_PROXY_ERROR_BODY) {
// Read and cache body
return connectExchange.readBodyAsync(ofByteArray())...
} else {
// Close connection without reading body
delegate.close();
return MinimalFuture.failedFuture(
new ProxyAuthenticationRequired(resp, null));
}
}
This would limit memory usage while still fixing the issue for most real-world
407 responses (which are typically small HTML error pages).
Alternatively, if there's a way to preserve the MultiExchange<Void> approach
while still making the body available to the application layer, I'd be happy to
explore that direction. Please let me know if you have suggestions.
I completely understand the timing concern regarding RDP 1. I'm happy to wait
until after the fork to continue this discussion. Thank you for considering
this contribution!
-------------
PR Comment: https://git.openjdk.org/jdk/pull/28232#issuecomment-3536668851