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
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
----------------------
* 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;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import static org.apache.solr.common.cloud.ZkStateReader.COLLECTION_PROP;
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.util.HashMap;
import java.util.HashSet;
@ -29,7 +33,9 @@ import java.util.Map;
import java.util.Set;
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.common.SolrException;
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.request.SolrQueryRequest;
import org.apache.solr.request.SolrRequestHandler;
import org.apache.solr.response.QueryResponseWriter;
import org.apache.solr.response.SolrQueryResponse;
import org.apache.solr.security.AuthorizationContext;
import org.apache.solr.servlet.HttpSolrCall;
@ -54,13 +59,7 @@ import org.apache.solr.servlet.SolrRequestParsers;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static org.apache.solr.common.cloud.ZkStateReader.COLLECTION_PROP;
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;
import com.google.common.collect.ImmutableSet;
// class that handle the '/v2' path
public class V2HttpCall extends HttpSolrCall {
@ -366,13 +365,6 @@ public class V2HttpCall extends HttpSolrCall {
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
protected ValidatingJsonMap getSpec() {
return api == null ? null : api.getSpec();

View File

@ -724,12 +724,20 @@ public class HttpSolrCall {
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() {
if (core != null) return core.getQueryResponseWriter(solrReq);
QueryResponseWriter respWriter = SolrCore.DEFAULT_RESPONSE_WRITERS.get(solrReq.getParams().get(CommonParams.WT));
if (respWriter == null) respWriter = SolrCore.DEFAULT_RESPONSE_WRITERS.get("standard");
return respWriter;
String wt = solrReq.getParams().get(CommonParams.WT);
if (core != null) {
return core.getQueryResponseWriter(wt);
} else {
return SolrCore.DEFAULT_RESPONSE_WRITERS.getOrDefault(wt,
SolrCore.DEFAULT_RESPONSE_WRITERS.get("standard"));
}
}
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.CloudSolrClient;
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.request.CollectionAdminRequest;
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"));
}
@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
public void testSingleWarning() throws Exception {
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
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`: