SOLR-13284: fallback to json instead of NPE and 500 code, when wt is omitted or wrong.

This commit is contained in:
Mikhail Khludnev 2019-03-10 23:10:13 +03:00
parent 9272c29539
commit e353dcfe7d
5 changed files with 60 additions and 24 deletions

View File

@ -108,6 +108,9 @@ Bug Fixes
* SOLR-13254: Correct message that is logged in solrj's ConnectionManager when an exception * SOLR-13254: Correct message that is logged in solrj's ConnectionManager when an exception
occurred while reconnecting to ZooKeeper. (hu xiaodong via Christine Poerschke) occurred while reconnecting to ZooKeeper. (hu xiaodong via Christine Poerschke)
* SOLR-13284: NullPointerException with 500 http status on omitted or wrong wt param.
It's fixed by fallback to json (Munendra S N via Mikhail Khludnev)
Improvements Improvements
---------------------- ----------------------
* SOLR-12999: Index replication could delete segments before downloading segments from master if there is not enough * SOLR-12999: Index replication could delete segments before downloading segments from master if there is not enough

View File

@ -17,8 +17,12 @@
package org.apache.solr.api; package org.apache.solr.api;
import javax.servlet.http.HttpServletRequest; import static org.apache.solr.common.cloud.ZkStateReader.COLLECTION_PROP;
import javax.servlet.http.HttpServletResponse; import static org.apache.solr.common.util.PathTrie.getPathSegments;
import static org.apache.solr.servlet.SolrDispatchFilter.Action.ADMIN;
import static org.apache.solr.servlet.SolrDispatchFilter.Action.PROCESS;
import static org.apache.solr.servlet.SolrDispatchFilter.Action.REMOTEQUERY;
import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodHandles;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
@ -29,7 +33,9 @@ import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.function.Supplier; import java.util.function.Supplier;
import com.google.common.collect.ImmutableSet; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.solr.client.solrj.SolrRequest; import org.apache.solr.client.solrj.SolrRequest;
import org.apache.solr.common.SolrException; import org.apache.solr.common.SolrException;
import org.apache.solr.common.cloud.DocCollection; import org.apache.solr.common.cloud.DocCollection;
@ -45,7 +51,6 @@ import org.apache.solr.handler.RequestHandlerUtils;
import org.apache.solr.logging.MDCLoggingContext; import org.apache.solr.logging.MDCLoggingContext;
import org.apache.solr.request.SolrQueryRequest; import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.request.SolrRequestHandler; import org.apache.solr.request.SolrRequestHandler;
import org.apache.solr.response.QueryResponseWriter;
import org.apache.solr.response.SolrQueryResponse; import org.apache.solr.response.SolrQueryResponse;
import org.apache.solr.security.AuthorizationContext; import org.apache.solr.security.AuthorizationContext;
import org.apache.solr.servlet.HttpSolrCall; import org.apache.solr.servlet.HttpSolrCall;
@ -54,13 +59,7 @@ import org.apache.solr.servlet.SolrRequestParsers;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import static org.apache.solr.common.cloud.ZkStateReader.COLLECTION_PROP; import com.google.common.collect.ImmutableSet;
import static org.apache.solr.common.params.CommonParams.JSON;
import static org.apache.solr.common.params.CommonParams.WT;
import static org.apache.solr.common.util.PathTrie.getPathSegments;
import static org.apache.solr.servlet.SolrDispatchFilter.Action.ADMIN;
import static org.apache.solr.servlet.SolrDispatchFilter.Action.PROCESS;
import static org.apache.solr.servlet.SolrDispatchFilter.Action.REMOTEQUERY;
// class that handle the '/v2' path // class that handle the '/v2' path
public class V2HttpCall extends HttpSolrCall { public class V2HttpCall extends HttpSolrCall {
@ -366,13 +365,6 @@ public class V2HttpCall extends HttpSolrCall {
return parts; return parts;
} }
@Override
protected QueryResponseWriter getResponseWriter() {
String wt = solrReq.getParams().get(WT, JSON);
if (core != null) return core.getResponseWriters().get(wt);
return SolrCore.DEFAULT_RESPONSE_WRITERS.get(wt);
}
@Override @Override
protected ValidatingJsonMap getSpec() { protected ValidatingJsonMap getSpec() {
return api == null ? null : api.getSpec(); return api == null ? null : api.getSpec();

View File

@ -724,12 +724,20 @@ public class HttpSolrCall {
writeResponse(solrResp, respWriter, Method.getMethod(req.getMethod())); writeResponse(solrResp, respWriter, Method.getMethod(req.getMethod()));
} }
/**
* Returns {@link QueryResponseWriter} to be used.
* When {@link CommonParams#WT} not specified in the request or specified value doesn't have
* corresponding {@link QueryResponseWriter} then, returns the default query response writer
* Note: This method must not return null
*/
protected QueryResponseWriter getResponseWriter() { protected QueryResponseWriter getResponseWriter() {
if (core != null) return core.getQueryResponseWriter(solrReq); String wt = solrReq.getParams().get(CommonParams.WT);
QueryResponseWriter respWriter = SolrCore.DEFAULT_RESPONSE_WRITERS.get(solrReq.getParams().get(CommonParams.WT)); if (core != null) {
if (respWriter == null) respWriter = SolrCore.DEFAULT_RESPONSE_WRITERS.get("standard"); return core.getQueryResponseWriter(wt);
return respWriter; } else {
return SolrCore.DEFAULT_RESPONSE_WRITERS.getOrDefault(wt,
SolrCore.DEFAULT_RESPONSE_WRITERS.get("standard"));
}
} }
protected void handleAdmin(SolrQueryResponse solrResp) { protected void handleAdmin(SolrQueryResponse solrResp) {

View File

@ -29,6 +29,7 @@ import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.impl.BinaryResponseParser; import org.apache.solr.client.solrj.impl.BinaryResponseParser;
import org.apache.solr.client.solrj.impl.CloudSolrClient; import org.apache.solr.client.solrj.impl.CloudSolrClient;
import org.apache.solr.client.solrj.impl.HttpSolrClient; import org.apache.solr.client.solrj.impl.HttpSolrClient;
import org.apache.solr.client.solrj.impl.NoOpResponseParser;
import org.apache.solr.client.solrj.impl.XMLResponseParser; import org.apache.solr.client.solrj.impl.XMLResponseParser;
import org.apache.solr.client.solrj.request.CollectionAdminRequest; import org.apache.solr.client.solrj.request.CollectionAdminRequest;
import org.apache.solr.client.solrj.request.V2Request; import org.apache.solr.client.solrj.request.V2Request;
@ -114,6 +115,34 @@ public class V2ApiIntegrationTest extends SolrCloudTestCase {
assertEquals("Command not found!", Utils.getObjectByPath(result, false, "/spec[0]/commands/XXXX")); assertEquals("Command not found!", Utils.getObjectByPath(result, false, "/spec[0]/commands/XXXX"));
} }
@SuppressWarnings("rawtypes")
@Test
public void testWTParam() throws Exception {
V2Request request = new V2Request.Builder("/c/" + COLL_NAME + "/get/_introspect").build();
// TODO: If possible do this in a better way
request.setResponseParser(new NoOpResponseParser("bleh"));
Map resp = resAsMap(cluster.getSolrClient(), request);
String respString = resp.toString();
assertFalse(respString.contains("<body><h2>HTTP ERROR 500</h2>"));
assertFalse(respString.contains("500"));
assertFalse(respString.contains("NullPointerException"));
assertFalse(respString.contains("<p>Problem accessing /solr/____v2/c/collection1/get/_introspect. Reason:"));
// since no-op response writer is used, doing contains match
assertTrue(respString.contains("/c/collection1/get"));
// no response parser
request.setResponseParser(null);
resp = resAsMap(cluster.getSolrClient(), request);
respString = resp.toString();
assertFalse(respString.contains("<body><h2>HTTP ERROR 500</h2>"));
assertFalse(respString.contains("<p>Problem accessing /solr/____v2/c/collection1/get/_introspect. Reason:"));
assertEquals("/c/collection1/get", Utils.getObjectByPath(resp, true, "/spec[0]/url/paths[0]"));
assertEquals(respString, 0, Utils.getObjectByPath(resp, true, "/responseHeader/status"));
}
@Test @Test
public void testSingleWarning() throws Exception { public void testSingleWarning() throws Exception {
NamedList resp = cluster.getSolrClient().request( NamedList resp = cluster.getSolrClient().request(

View File

@ -39,7 +39,11 @@ The `wt` parameter selects the Response Writer to be used. The list below descri
== JSON Response Writer == JSON Response Writer
The default Solr Response Writer is the `JsonResponseWriter`, which formats output in JavaScript Object Notation (JSON), a lightweight data interchange format specified in specified in RFC 4627. If you do not set the `wt` parameter in your request, you will get JSON by default. The default Solr Response Writer is the `JsonResponseWriter`, which formats output in JavaScript Object Notation (JSON), a lightweight data interchange format specified in specified in RFC 4627.
The default response writer is used when,
* `wt` parameter is not specified in the request
* non-existent response writer is specified
Here is a sample response for a simple query like `q=id:VS1GB400C3`: Here is a sample response for a simple query like `q=id:VS1GB400C3`: