This is an automated email from the ASF dual-hosted git repository. jdyer pushed a commit to branch feature/SOLR-17771 in repository https://gitbox.apache.org/repos/asf/solr.git
commit 4f3157720fff82c8f981f4a138ffdc28720d59da Author: jdyer1 <[email protected]> AuthorDate: Tue Oct 14 14:32:26 2025 -0500 Enhance JDK client to track if it has issued a HEAD request by unique base URI --- .../solr/client/solrj/impl/HttpJdkSolrClient.java | 28 ++++++++++++---------- .../client/solrj/impl/HttpJdkSolrClientTest.java | 18 ++++++++++---- 2 files changed, 29 insertions(+), 17 deletions(-) diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/HttpJdkSolrClient.java b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/HttpJdkSolrClient.java index 15e686d5773..54ca3b8b8b7 100644 --- a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/HttpJdkSolrClient.java +++ b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/HttpJdkSolrClient.java @@ -34,11 +34,13 @@ import java.net.http.HttpTimeoutException; import java.time.Duration; import java.time.temporal.ChronoUnit; import java.util.Collection; +import java.util.HashMap; import java.util.Locale; import java.util.Map; import java.util.Objects; import java.util.concurrent.BlockingQueue; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; import java.util.concurrent.LinkedBlockingQueue; @@ -379,17 +381,6 @@ public class HttpJdkSolrClient extends HttpSolrClientBase { if (forceHttp11 || url == null || url.toLowerCase(Locale.ROOT).startsWith("https://")) { return true; } - return maybeTryHeadRequestSync(url); - } - - protected volatile boolean headRequested; // must be threadsafe - private boolean headSucceeded; // must be threadsafe - - private synchronized boolean maybeTryHeadRequestSync(String url) { - if (headRequested) { - return headSucceeded; - } - URI uriNoQueryParams; try { uriNoQueryParams = new URI(url); @@ -397,6 +388,17 @@ public class HttpJdkSolrClient extends HttpSolrClientBase { // If the url is invalid, let a subsequent request try again. return false; } + return maybeTryHeadRequestSync(uriNoQueryParams); + } + + protected Map<URI, Boolean> headSucceededByBaseUri = new HashMap<>(); // use only in synchronized method + + private synchronized boolean maybeTryHeadRequestSync(URI uriNoQueryParams) { + Boolean headSucceeded = headSucceededByBaseUri.get(uriNoQueryParams); + if (headSucceeded !=null) { + return headSucceeded; + } + HttpRequest.Builder headReqB = HttpRequest.newBuilder(uriNoQueryParams) .method("HEAD", HttpRequest.BodyPublishers.noBody()) @@ -406,7 +408,7 @@ public class HttpJdkSolrClient extends HttpSolrClientBase { httpClient.send(headReqB.build(), HttpResponse.BodyHandlers.discarding()); headSucceeded = true; } catch (IOException ioe) { - log.warn("Could not issue HEAD request to {} ", url, ioe); + log.warn("Could not issue HEAD request to {} ", uriNoQueryParams, ioe); headSucceeded = false; } catch (InterruptedException ie) { Thread.currentThread().interrupt(); @@ -414,7 +416,7 @@ public class HttpJdkSolrClient extends HttpSolrClientBase { } finally { // The HEAD request is tried only once. All future requests will skip this check. - headRequested = true; + headSucceededByBaseUri.put(uriNoQueryParams, headSucceeded); if (!headSucceeded) { log.info("All unencrypted POST requests with a chunked body will use http/1.1"); diff --git a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/HttpJdkSolrClientTest.java b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/HttpJdkSolrClientTest.java index e6a47680bc8..9bd418e7e6c 100644 --- a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/HttpJdkSolrClientTest.java +++ b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/HttpJdkSolrClientTest.java @@ -20,6 +20,8 @@ package org.apache.solr.client.solrj.impl; import java.io.IOException; import java.net.CookieHandler; import java.net.CookieManager; +import java.net.URI; +import java.net.URISyntaxException; import java.net.http.HttpClient; import java.util.Arrays; import java.util.Collections; @@ -328,9 +330,9 @@ public class HttpJdkSolrClientTest extends HttpSolrClientTestBase { testUpdate(client, HttpSolrClientTestBase.WT.XML, "application/xml; charset=UTF-8", value); if (http11) { assertEquals(HttpClient.Version.HTTP_1_1, client.httpClient.version()); - assertFalse( + assertNull( "The HEAD request should not be performed if already forcing Http/1.1.", - client.headRequested); + client.headSucceededByBaseUri.get(baseUri())); } else { assertEquals(HttpClient.Version.HTTP_2, client.httpClient.version()); } @@ -504,7 +506,7 @@ public class HttpJdkSolrClientTest extends HttpSolrClientTestBase { assertTrue(client.maybeTryHeadRequest(url)); // if https, the client won't attempt a HEAD request - if (client.headRequested) { + if (!client.headSucceededByBaseUri.isEmpty()) { assertEquals("head", DebugServlet.lastMethod); assertTrue(DebugServlet.headers.containsKey("content-type")); } @@ -524,7 +526,15 @@ public class HttpJdkSolrClientTest extends HttpSolrClientTestBase { private void assertNoHeadRequestWithSsl(HttpJdkSolrClient client) { if (isSSLMode()) { - assertFalse("The HEAD request should not be performed if using SSL.", client.headRequested); + assertNull("The HEAD request should not be performed if using SSL.", client.headSucceededByBaseUri.get(baseUri())); + } + } + + private URI baseUri() { + try { + return new URI(getBaseUrl()); + } catch(URISyntaxException e) { + throw new RuntimeException(e); } }
