diff --git a/src/main/scala/io/ino/solrs/AsyncSolrClient.scala b/src/main/scala/io/ino/solrs/AsyncSolrClient.scala index e11be45..cad7d61 100644 --- a/src/main/scala/io/ino/solrs/AsyncSolrClient.scala +++ b/src/main/scala/io/ino/solrs/AsyncSolrClient.scala @@ -720,7 +720,7 @@ class AsyncSolrClient[F[_]] protected (private[solrs] val loadBalancer: LoadBala @throws[RemoteSolrException] private def validateResponse(response: Response, responseParser: ResponseParser)(implicit server: SolrServer): Unit = { - validateMimeType(responseParser.getContentType, response) + validateMimeType(responseParser.getContentTypes.asScala, response) val httpStatus = response.getStatusCode if(httpStatus >= 400) { @@ -731,30 +731,33 @@ class AsyncSolrClient[F[_]] protected (private[solrs] val loadBalancer: LoadBala } @throws[RemoteSolrException] - protected def validateMimeType(expectedContentType: String, response: Response): Unit = { - if (expectedContentType != null) { - val expectedMimeType = getMimeType(expectedContentType).map(_.toLowerCase(Locale.ROOT)).getOrElse("") - val actualMimeType = getMimeType(response.getContentType).map(_.toLowerCase(Locale.ROOT)).getOrElse("") - if (expectedMimeType != actualMimeType) { - var msg = s"Expected mime type [$expectedMimeType] but got [$actualMimeType]." - var encoding: String = getResponseEncoding(response) - try { - // might be solved with responseParser.processResponse (like it's done for 4xx codes) - msg = msg + "\n" + IOUtils.toString(response.getResponseBodyAsStream, encoding) - } - catch { - case e: IOException => - metrics.countRemoteException - throw new RemoteSolrException(response.getStatusCode, s"$msg Unfortunately could not parse response (for debugging) with encoding $encoding", e) - } - metrics.countRemoteException - throw new RemoteSolrException(response.getStatusCode, msg, null) + protected def validateMimeType(supportedContentTypes: Iterable[String], response: Response): Unit = { + val actualMimeType = getMimeType(response.getContentType).map(_.toLowerCase(Locale.ROOT)).getOrElse("") + val matchingMimeType = supportedContentTypes.find { supportedContentType => + val expectedMimeType = getMimeType(supportedContentType).map(_.toLowerCase(Locale.ROOT)).getOrElse("") + expectedMimeType == actualMimeType + } + + if (matchingMimeType.isEmpty) { + var msg = s"Expected a mime type of [${supportedContentTypes.mkString(", ")}] but got [$actualMimeType]." + val encoding: String = getResponseEncoding(response) + try { + // might be solved with responseParser.processResponse (like it's done for 4xx codes) + msg = msg + "\n" + IOUtils.toString(response.getResponseBodyAsStream, encoding) + } + catch { + case e: IOException => + metrics.countRemoteException + throw new RemoteSolrException(response.getStatusCode, s"$msg Unfortunately could not parse response (for debugging) with encoding $encoding", e) } + metrics.countRemoteException + throw new RemoteSolrException(response.getStatusCode, msg, null) + } } protected def getResponseEncoding(response: Response): String = { - var encoding = response.getHeader("Content-Encoding") + val encoding = response.getHeader("Content-Encoding") if (encoding == null) "UTF-8" else encoding } diff --git a/src/test/scala/io/ino/solrs/AsyncSolrClientIntegrationSpec.scala b/src/test/scala/io/ino/solrs/AsyncSolrClientIntegrationSpec.scala index 326717b..cf281c2 100644 --- a/src/test/scala/io/ino/solrs/AsyncSolrClientIntegrationSpec.scala +++ b/src/test/scala/io/ino/solrs/AsyncSolrClientIntegrationSpec.scala @@ -6,10 +6,12 @@ import org.asynchttpclient.DefaultAsyncHttpClient import org.apache.solr.client.solrj.SolrQuery import org.apache.solr.client.solrj.SolrRequest import org.apache.solr.client.solrj.SolrResponse +import org.apache.solr.client.solrj.impl.BinaryResponseParser +import org.apache.solr.client.solrj.impl.BinaryResponseParser.BINARY_CONTENT_TYPE +import org.apache.solr.client.solrj.impl.BinaryResponseParser.BINARY_CONTENT_TYPE_V2 import org.apache.solr.client.solrj.impl.{NoOpResponseParser, XMLResponseParser} import org.apache.solr.client.solrj.request.{GenericSolrRequest, QueryRequest} import org.apache.solr.client.solrj.response.QueryResponse -import org.mockito.ArgumentMatcher._ import org.mockito.ArgumentMatchers.anyLong import org.mockito.Mockito.verify import org.scalatest.concurrent.Eventually._ @@ -18,6 +20,7 @@ import org.scalatest.concurrent.PatienceConfiguration.Timeout import org.scalatest.time.Millis import org.scalatest.time.Span +import java.util import scala.annotation.tailrec import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.Future @@ -123,7 +126,9 @@ class AsyncSolrClientIntegrationSpec extends StandardFunSpec with RunningSolr { null, new SolrQuery("cat:cat1").add("wt", "xml") ) - request.setResponseParser(new NoOpResponseParser) + request.setResponseParser(new NoOpResponseParser { + override def getContentTypes: util.Collection[String] = asList("application/xml") + }) val response = solr.execute(request) @@ -151,7 +156,9 @@ class AsyncSolrClientIntegrationSpec extends StandardFunSpec with RunningSolr { awaitReady(response) a [RemoteSolrException] should be thrownBy await(response) // embedded Jetty returns 404 with text/html response with error message in body - (the [RemoteSolrException] thrownBy await(response)).getMessage should include ("Expected mime type [] but got [text/html]") + val mimeTypesRegex = s"($BINARY_CONTENT_TYPE, $BINARY_CONTENT_TYPE_V2|$BINARY_CONTENT_TYPE_V2, $BINARY_CONTENT_TYPE)" + (the [RemoteSolrException] thrownBy await(response)).getMessage should include regex "Expected a mime type of " + + s"\\[$mimeTypesRegex\\] but got \\[text/html\\]" solr.shutdown() }