This is an automated email from the ASF dual-hosted git repository.

dsmiley pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/solr.git


The following commit(s) were added to refs/heads/main by this push:
     new ad2d914f208 HttpSolrClient: improve error when text/html (#4526)
ad2d914f208 is described below

commit ad2d914f208b4ae5a1858e0138024eaa6bb96fc8
Author: David Smiley <[email protected]>
AuthorDate: Mon Jun 22 22:21:29 2026 -0400

    HttpSolrClient: improve error when text/html (#4526)
    
    made error messages more consistent, avoiding complaining about the 
content-type when it's text/html
    Ex: 429 will clearly give that code and not complain about unexpected 
text/html.  Curiously, this happened less for Apache HttpClient.
---
 .../PR#4526-HttpSolrClient-error-message.yml       |  9 ++++++++
 .../solr/cloud/TestAuthenticationFramework.java    | 13 ++++--------
 .../solr/security/BasicAuthIntegrationTest.java    |  2 +-
 .../solr/servlet/TestRequestRateLimiter.java       | 17 +++++++++++----
 .../solr/client/solrj/impl/HttpSolrClient.java     | 24 ++++++++++------------
 5 files changed, 38 insertions(+), 27 deletions(-)

diff --git a/changelog/unreleased/PR#4526-HttpSolrClient-error-message.yml 
b/changelog/unreleased/PR#4526-HttpSolrClient-error-message.yml
new file mode 100644
index 00000000000..ecf4bfc9a6d
--- /dev/null
+++ b/changelog/unreleased/PR#4526-HttpSolrClient-error-message.yml
@@ -0,0 +1,9 @@
+title: >
+  HttpSolrClient: made error messages more consistent, avoiding complaining 
about the content-type
+  when it's text/html
+type: changed
+authors:
+  - name: David Smiley
+links:
+  - name: PR#4526
+    url: https://github.com/apache/solr/pull/4526
diff --git 
a/solr/core/src/test/org/apache/solr/cloud/TestAuthenticationFramework.java 
b/solr/core/src/test/org/apache/solr/cloud/TestAuthenticationFramework.java
index 130e288ee96..18060fcd016 100644
--- a/solr/core/src/test/org/apache/solr/cloud/TestAuthenticationFramework.java
+++ b/solr/core/src/test/org/apache/solr/cloud/TestAuthenticationFramework.java
@@ -21,7 +21,7 @@ import jakarta.servlet.http.HttpServletRequest;
 import jakarta.servlet.http.HttpServletResponse;
 import java.lang.invoke.MethodHandles;
 import java.util.Map;
-import org.apache.solr.client.solrj.SolrServerException;
+import org.apache.solr.client.solrj.RemoteSolrException;
 import org.apache.solr.client.solrj.impl.CloudSolrClient;
 import org.apache.solr.client.solrj.request.CollectionAdminRequest;
 import org.apache.solr.client.solrj.request.SolrQuery;
@@ -43,9 +43,6 @@ public class TestAuthenticationFramework extends 
SolrCloudTestCase {
   private static final String configName = "solrCloudCollectionConfig";
   private static final String collectionName = "testcollection";
 
-  static String requestUsername = MockAuthenticationPlugin.expectedUsername;
-  static String requestPassword = MockAuthenticationPlugin.expectedPassword;
-
   @Override
   public void setUp() throws Exception {
     setupAuthenticationPlugin();
@@ -70,11 +67,9 @@ public class TestAuthenticationFramework extends 
SolrCloudTestCase {
 
     // Should fail with 401
     try {
-      SolrServerException e =
-          expectThrows(SolrServerException.class, 
this::collectionCreateSearchDeleteTwice);
-      assertTrue(
-          "Should've returned a 401 error",
-          e.getMessage().contains("401") || 
e.getMessage().contains("Authentication"));
+      RemoteSolrException e =
+          expectThrows(RemoteSolrException.class, 
this::collectionCreateSearchDeleteTwice);
+      assertEquals(401, e.code()); // Authentication failed
     } finally {
       MockAuthenticationPlugin.expectedUsername = null;
       MockAuthenticationPlugin.expectedPassword = null;
diff --git 
a/solr/core/src/test/org/apache/solr/security/BasicAuthIntegrationTest.java 
b/solr/core/src/test/org/apache/solr/security/BasicAuthIntegrationTest.java
index 166b9f440c6..9684d5447cf 100644
--- a/solr/core/src/test/org/apache/solr/security/BasicAuthIntegrationTest.java
+++ b/solr/core/src/test/org/apache/solr/security/BasicAuthIntegrationTest.java
@@ -259,7 +259,7 @@ public class BasicAuthIntegrationTest extends 
SolrCloudAuthTestCase {
               () -> {
                 new UpdateRequest().deleteByQuery("*:*").process(aNewClient, 
COLLECTION);
               });
-      assertTrue(e.getMessage(), e.getMessage().contains("Authentication 
failed"));
+      assertEquals(401, e.code()); // Authentication failed
     } finally {
       aNewClient.close();
       cluster.stopJettySolrRunner(aNewJetty);
diff --git 
a/solr/core/src/test/org/apache/solr/servlet/TestRequestRateLimiter.java 
b/solr/core/src/test/org/apache/solr/servlet/TestRequestRateLimiter.java
index 87ec473b13a..0054cd1ad19 100644
--- a/solr/core/src/test/org/apache/solr/servlet/TestRequestRateLimiter.java
+++ b/solr/core/src/test/org/apache/solr/servlet/TestRequestRateLimiter.java
@@ -38,12 +38,14 @@ import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.LongAdder;
-import org.apache.lucene.tests.util.LuceneTestCase;
 import org.apache.solr.SolrTestCaseJ4;
 import org.apache.solr.client.solrj.RemoteSolrException;
 import org.apache.solr.client.solrj.SolrClient;
 import org.apache.solr.client.solrj.SolrRequest;
 import org.apache.solr.client.solrj.impl.CloudSolrClient;
+import org.apache.solr.client.solrj.impl.ZkClientClusterStateProvider;
+import org.apache.solr.client.solrj.jetty.CloudJettySolrClient;
+import org.apache.solr.client.solrj.jetty.HttpJettySolrClient;
 import org.apache.solr.client.solrj.request.CollectionAdminRequest;
 import org.apache.solr.client.solrj.request.SolrQuery;
 import org.apache.solr.client.solrj.response.QueryResponse;
@@ -56,7 +58,6 @@ import org.junit.BeforeClass;
 import org.junit.Test;
 import org.mockito.Mockito;
 
[email protected](bugUrl = 
"https://issues.apache.org/jira/browse/SOLR-17810";)
 public class TestRequestRateLimiter extends SolrCloudTestCase {
   private static final String FIRST_COLLECTION = "c1";
   private static final String SECOND_COLLECTION = "c2";
@@ -69,7 +70,7 @@ public class TestRequestRateLimiter extends SolrCloudTestCase 
{
 
   @Test
   public void testConcurrentQueries() throws Exception {
-    try (CloudSolrClient client = cluster.newSolrClient(FIRST_COLLECTION)) {
+    try (CloudSolrClient client = newHttp1SolrClient(FIRST_COLLECTION)) {
 
       CollectionAdminRequest.createCollection(FIRST_COLLECTION, 1, 
1).process(client);
       cluster.waitForActiveCollection(FIRST_COLLECTION, 1, 1);
@@ -289,7 +290,7 @@ public class TestRequestRateLimiter extends 
SolrCloudTestCase {
 
   @Nightly
   public void testSlotBorrowing() throws Exception {
-    try (CloudSolrClient client = cluster.newSolrClient(SECOND_COLLECTION)) {
+    try (CloudSolrClient client = newHttp1SolrClient(SECOND_COLLECTION)) {
 
       CollectionAdminRequest.createCollection(SECOND_COLLECTION, 1, 
1).process(client);
       cluster.waitForActiveCollection(SECOND_COLLECTION, 1, 1);
@@ -429,6 +430,14 @@ public class TestRequestRateLimiter extends 
SolrCloudTestCase {
     }
   }
 
+  private CloudSolrClient newHttp1SolrClient(String collection) {
+    return new CloudJettySolrClient.Builder(
+            new 
ZkClientClusterStateProvider(cluster.getZkServer().getZkAddress()))
+        .withDefaultCollection(collection)
+        .withHttpClientBuilder(new 
HttpJettySolrClient.Builder().useHttp1_1(true))
+        .build();
+  }
+
   private static class MockBuilder extends RateLimitManager.Builder {
     private final RequestRateLimiter queryRequestRateLimiter;
     private final RequestRateLimiter indexRequestRateLimiter;
diff --git 
a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/HttpSolrClient.java 
b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/HttpSolrClient.java
index 93ae9e332f1..d1e69255bab 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/HttpSolrClient.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/HttpSolrClient.java
@@ -23,11 +23,11 @@ import java.io.InputStream;
 import java.lang.invoke.MethodHandles;
 import java.lang.reflect.Constructor;
 import java.net.MalformedURLException;
-import java.net.URLDecoder;
 import java.nio.charset.Charset;
 import java.nio.charset.StandardCharsets;
 import java.util.Base64;
 import java.util.Collection;
+import java.util.Objects;
 import java.util.Set;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.ExecutorService;
@@ -188,11 +188,12 @@ public abstract class HttpSolrClient extends SolrClient {
       String responseMethod,
       final ResponseParser processor,
       InputStream is,
-      String mimeType,
+      String mimeType, // aka contentType
       String encoding,
       final boolean isV2Api,
       String urlExceptionMessage)
       throws SolrServerException {
+    Objects.requireNonNull(processor);
     boolean shouldClose = true;
     try {
       // handle some http level checks before trying to parse the response
@@ -209,7 +210,7 @@ public abstract class HttpSolrClient extends SolrClient {
           }
           break;
         default:
-          if (processor == null || mimeType == null) {
+          if (mimeType == null || mimeType.equals("text/html")) {
             throw new RemoteSolrException(
                 urlExceptionMessage,
                 httpStatus,
@@ -218,6 +219,8 @@ public abstract class HttpSolrClient extends SolrClient {
           }
       }
 
+      checkContentType(processor, is, mimeType, encoding, httpStatus, 
urlExceptionMessage);
+
       if (wantStream(processor)) {
         // Only case where stream should not be closed
         shouldClose = false;
@@ -225,8 +228,6 @@ public abstract class HttpSolrClient extends SolrClient {
         return 
InputStreamResponseParser.createInputStreamNamedList(httpStatus, is);
       }
 
-      checkContentType(processor, is, mimeType, encoding, httpStatus, 
urlExceptionMessage);
-
       NamedList<Object> rsp;
       try {
         rsp = processor.processResponse(is, encoding);
@@ -240,14 +241,11 @@ public abstract class HttpSolrClient extends SolrClient {
       }
       if (httpStatus != 200 && !isV2Api) {
         if (error == null) {
-          StringBuilder msg =
-              new StringBuilder()
-                  .append(responseReason)
-                  .append("\n")
-                  .append("request: ")
-                  .append(responseMethod);
-          String reason = URLDecoder.decode(msg.toString(), FALLBACK_CHARSET);
-          throw new RemoteSolrException(urlExceptionMessage, httpStatus, 
reason, null);
+          throw new RemoteSolrException(
+              urlExceptionMessage,
+              httpStatus,
+              "non ok status: " + httpStatus + ", message:" + responseReason,
+              null);
         } else {
           throw new RemoteSolrException(urlExceptionMessage, httpStatus, 
error);
         }

Reply via email to