8350991: Improve HTTP client header handling

Reviewed-by: rhalade, dfuchs, michaelm
This commit is contained in:
Darragh Clarke 2025-04-17 13:11:59 +00:00 committed by Jaikiran Pai
parent 3ec6eb6482
commit 5ae719c8fc
3 changed files with 33 additions and 5 deletions

View File

@ -39,6 +39,7 @@ import java.util.Optional;
import java.net.http.HttpClient;
import java.net.http.HttpHeaders;
import java.net.http.HttpRequest;
import java.util.function.BiPredicate;
import jdk.internal.net.http.common.Alpns;
import jdk.internal.net.http.common.HttpHeadersBuilder;
@ -148,7 +149,11 @@ public class HttpRequestImpl extends HttpRequest implements WebSocketRequest {
String method,
HttpRequestImpl other,
boolean mayHaveBody) {
return new HttpRequestImpl(uri, method, other, mayHaveBody);
if (uri.getScheme().equalsIgnoreCase(other.uri.getScheme()) &&
uri.getRawAuthority().equals(other.uri.getRawAuthority())) {
return new HttpRequestImpl(uri, method, other, mayHaveBody, Optional.empty());
}
return new HttpRequestImpl(uri, method, other, mayHaveBody, Optional.of(Utils.ALLOWED_REDIRECT_HEADERS));
}
/** Returns a new instance suitable for authentication. */
@ -168,9 +173,19 @@ public class HttpRequestImpl extends HttpRequest implements WebSocketRequest {
String method,
HttpRequestImpl other,
boolean mayHaveBody) {
this(uri, method, other, mayHaveBody, Optional.empty());
}
private HttpRequestImpl(URI uri,
String method,
HttpRequestImpl other,
boolean mayHaveBody,
Optional<BiPredicate<String, String>> redirectHeadersFilter) {
assert method == null || Utils.isValidName(method);
this.method = method == null? "GET" : method;
this.userHeaders = other.userHeaders;
this.method = method == null ? "GET" : method;
HttpHeaders userHeaders = redirectHeadersFilter.isPresent() ?
HttpHeaders.of(other.userHeaders.map(), redirectHeadersFilter.get()) : other.userHeaders;
this.userHeaders = userHeaders;
this.isWebSocket = other.isWebSocket;
this.systemHeadersBuilder = new HttpHeadersBuilder();
if (userHeaders.firstValue("User-Agent").isEmpty()) {

View File

@ -188,6 +188,18 @@ public final class Utils {
public static final BiPredicate<String, String>
ALLOWED_HEADERS = (header, unused) -> !DISALLOWED_HEADERS_SET.contains(header);
private static final Set<String> DISALLOWED_REDIRECT_HEADERS_SET = getDisallowedRedirectHeaders();
private static Set<String> getDisallowedRedirectHeaders() {
Set<String> headers = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
headers.addAll(Set.of("Authorization", "Cookie", "Origin", "Referer", "Host"));
return Collections.unmodifiableSet(headers);
}
public static final BiPredicate<String, String>
ALLOWED_REDIRECT_HEADERS = (header, _) -> !DISALLOWED_REDIRECT_HEADERS_SET.contains(header);
public static final BiPredicate<String, String> VALIDATE_USER_HEADER =
(name, value) -> {
assert name != null : "null header name";

View File

@ -261,8 +261,9 @@ public class DigestEchoClient {
}
try {
for (DigestEchoServer.HttpAuthType authType : types) {
// The test server does not support PROXY305 properly
if (authType == DigestEchoServer.HttpAuthType.PROXY305) continue;
// The test server does not support PROXY305 or SERVER307 properly
if (authType == DigestEchoServer.HttpAuthType.PROXY305 ||
authType == DigestEchoServer.HttpAuthType.SERVER307) continue;
EnumSet<DigestEchoServer.HttpAuthSchemeType> basics =
EnumSet.of(DigestEchoServer.HttpAuthSchemeType.BASICSERVER,
DigestEchoServer.HttpAuthSchemeType.BASIC);