You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@solr.apache.org by st...@apache.org on 2023/08/22 16:27:27 UTC

[solr] branch main updated: SOLR-16929 SolrStream propagates undecoded error message (#1852)

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

stillalex 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 c7b58302d33 SOLR-16929 SolrStream propagates undecoded error message (#1852)
c7b58302d33 is described below

commit c7b58302d334795e1c820f2a28903b64bce91e59
Author: Alex D <st...@apache.org>
AuthorDate: Tue Aug 22 09:27:21 2023 -0700

    SOLR-16929 SolrStream propagates undecoded error message (#1852)
---
 solr/CHANGES.txt                                   |  2 ++
 .../solrj/io/stream/JavabinTupleStreamParser.java  | 24 +++++++++++--
 .../solr/client/solrj/io/stream/SolrStream.java    |  3 +-
 .../solr/client/solrj/io/stream/StreamingTest.java | 40 ++++++++++++++++++----
 4 files changed, 60 insertions(+), 9 deletions(-)

diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index e09b1849394..66e12ec7384 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -130,6 +130,8 @@ Bug Fixes
 
 * SOLR-16859: Missing Proxy support for Http2SolrClient (Alex Deparvu)
 
+* SOLR-16929: SolrStream propagates undecoded error message (Alex Deparvu)
+
 Dependency Upgrades
 ---------------------
 
diff --git a/solr/solrj-streaming/src/java/org/apache/solr/client/solrj/io/stream/JavabinTupleStreamParser.java b/solr/solrj-streaming/src/java/org/apache/solr/client/solrj/io/stream/JavabinTupleStreamParser.java
index 751d833168f..5209d29e4be 100644
--- a/solr/solrj-streaming/src/java/org/apache/solr/client/solrj/io/stream/JavabinTupleStreamParser.java
+++ b/solr/solrj-streaming/src/java/org/apache/solr/client/solrj/io/stream/JavabinTupleStreamParser.java
@@ -24,6 +24,7 @@ import java.util.ArrayList;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 import org.apache.solr.common.util.DataInputInputStream;
 import org.apache.solr.common.util.FastInputStream;
 import org.apache.solr.common.util.JavaBinCodec;
@@ -34,12 +35,12 @@ public class JavabinTupleStreamParser extends JavaBinCodec implements TupleStrea
   private int arraySize = Integer.MAX_VALUE;
   private boolean onlyJsonTypes = false;
   int objectSize;
+  private boolean atDocs;
 
   public JavabinTupleStreamParser(InputStream is, boolean onlyJsonTypes) throws IOException {
     this.onlyJsonTypes = onlyJsonTypes;
     this.is = is;
     this.fis = initRead(is);
-    if (!readTillDocs()) arraySize = 0;
   }
 
   private boolean readTillDocs() throws IOException {
@@ -61,6 +62,9 @@ public class JavabinTupleStreamParser extends JavaBinCodec implements TupleStrea
             return true;
           }
           return false;
+        } else if ("error".equals(k)) {
+          handleError();
+          return true;
         } else {
           if (readTillDocs()) return true;
         }
@@ -91,7 +95,7 @@ public class JavabinTupleStreamParser extends JavaBinCodec implements TupleStrea
     return tagByte == SOLRDOCLST;
   }
 
-  private Map<?, ?> readAsMap(DataInputInputStream dis) throws IOException {
+  private Map<String, ?> readAsMap(DataInputInputStream dis) throws IOException {
     int sz = readSize(dis);
     Map<String, Object> m = new LinkedHashMap<>();
     for (int i = 0; i < sz; i++) {
@@ -175,6 +179,14 @@ public class JavabinTupleStreamParser extends JavaBinCodec implements TupleStrea
   @Override
   @SuppressWarnings({"unchecked"})
   public Map<String, Object> next() throws IOException {
+    if (!atDocs) {
+      atDocs = true;
+      if (!readTillDocs()) {
+        arraySize = 0;
+        return null;
+      }
+    }
+
     if (arraySize == 0) return null;
     Object o = readVal(fis);
     arraySize--;
@@ -186,4 +198,12 @@ public class JavabinTupleStreamParser extends JavaBinCodec implements TupleStrea
   public void close() throws IOException {
     is.close();
   }
+
+  private void handleError() throws IOException {
+    tagByte = fis.readByte();
+    var error = readAsMap(fis);
+    var msg =
+        Optional.ofNullable(error.get("msg")).map(String::valueOf).orElse("Unknown Exception");
+    throw new SolrStream.HandledException(msg);
+  }
 }
diff --git a/solr/solrj-streaming/src/java/org/apache/solr/client/solrj/io/stream/SolrStream.java b/solr/solrj-streaming/src/java/org/apache/solr/client/solrj/io/stream/SolrStream.java
index f58546cb432..ce4d31babaa 100644
--- a/solr/solrj-streaming/src/java/org/apache/solr/client/solrj/io/stream/SolrStream.java
+++ b/solr/solrj-streaming/src/java/org/apache/solr/client/solrj/io/stream/SolrStream.java
@@ -315,7 +315,8 @@ public class SolrStream extends TupleStream {
       statusCode = (int) genericResponse.get("responseStatus");
     }
 
-    if (statusCode != 200) {
+    if (statusCode == 401
+        || statusCode == 403) { // auth response comes as html, so propagate as string
       String errMsg = consumeStreamAsErrorMessage(stream);
       if (httpResponse != null) {
         httpResponse.close();
diff --git a/solr/solrj-streaming/src/test/org/apache/solr/client/solrj/io/stream/StreamingTest.java b/solr/solrj-streaming/src/test/org/apache/solr/client/solrj/io/stream/StreamingTest.java
index 295fca76f9f..d8770711876 100644
--- a/solr/solrj-streaming/src/test/org/apache/solr/client/solrj/io/stream/StreamingTest.java
+++ b/solr/solrj-streaming/src/test/org/apache/solr/client/solrj/io/stream/StreamingTest.java
@@ -627,7 +627,6 @@ public class StreamingTest extends SolrCloudTestCase {
   }
 
   @Test
-  @Ignore
   public void testExceptionStream() throws Exception {
 
     helloDocsUpdateRequest.commit(cluster.getSolrClient(), COLLECTIONORALIAS);
@@ -635,8 +634,8 @@ public class StreamingTest extends SolrCloudTestCase {
     StreamContext streamContext = new StreamContext();
     SolrClientCache solrClientCache = new SolrClientCache();
     streamContext.setSolrClientCache(solrClientCache);
-    // Test an error that comes originates from the /select handler
     try {
+      // Test an error that originates from the /select handler
       SolrParams sParamsA = params("q", "*:*", "fl", "a_s,a_i,a_f,blah", "sort", "blah asc");
       CloudSolrStream stream = new CloudSolrStream(zkHost, COLLECTIONORALIAS, sParamsA);
       ExceptionStream estream = new ExceptionStream(stream);
@@ -646,16 +645,45 @@ public class StreamingTest extends SolrCloudTestCase {
       assertTrue(t.EXCEPTION);
       assertTrue(t.getException().contains("sort param field can't be found: blah"));
 
-      // Test an error that comes originates from the /export handler
-      sParamsA = params("q", "*:*", "fl", "a_s,a_i,a_f,score", "sort", "a_s asc", "qt", "/export");
+      sParamsA = params("q", "*:*", "fl", "a_s,a_i,a_f,blah", "sort", "blah asc", "wt", "javabin");
       stream = new CloudSolrStream(zkHost, COLLECTIONORALIAS, sParamsA);
       estream = new ExceptionStream(stream);
       estream.setStreamContext(streamContext);
       t = getTuple(estream);
       assertTrue(t.EOF);
       assertTrue(t.EXCEPTION);
-      // The /export handler will pass through a real exception.
-      assertTrue(t.getException().contains("undefined field:"));
+      assertTrue(t.getException().contains("sort param field can't be found: blah"));
+
+      // Test an error that originates from the /export handler
+      sParamsA = params("q", "*:*", "fl", "a_s,a_i,a_f,blah", "sort", "blah asc", "qt", "/export");
+      stream = new CloudSolrStream(zkHost, COLLECTIONORALIAS, sParamsA);
+      estream = new ExceptionStream(stream);
+      estream.setStreamContext(streamContext);
+      t = getTuple(estream);
+      assertTrue(t.EOF);
+      assertTrue(t.EXCEPTION);
+      assertTrue(t.getException().contains("sort param field can't be found: blah"));
+
+      // Test an error that originates from the /export handler
+      sParamsA =
+          params(
+              "q",
+              "*:*",
+              "fl",
+              "a_s,a_i,a_f,blah",
+              "sort",
+              "blah asc",
+              "qt",
+              "/export",
+              "wt",
+              "javabin");
+      stream = new CloudSolrStream(zkHost, COLLECTIONORALIAS, sParamsA);
+      estream = new ExceptionStream(stream);
+      estream.setStreamContext(streamContext);
+      t = getTuple(estream);
+      assertTrue(t.EOF);
+      assertTrue(t.EXCEPTION);
+      assertTrue(t.getException().contains("sort param field can't be found: blah"));
     } finally {
       solrClientCache.close();
     }