Skip to content

SOLR-18085: Review use of "wt=standard" and see if we can remove it.#4080

Open
epugh wants to merge 16 commits intoapache:mainfrom
epugh:SOLR-18085
Open

SOLR-18085: Review use of "wt=standard" and see if we can remove it.#4080
epugh wants to merge 16 commits intoapache:mainfrom
epugh:SOLR-18085

Conversation

@epugh
Copy link
Contributor

@epugh epugh commented Jan 27, 2026

https://issues.apache.org/jira/browse/SOLR-18085

Description

The use of wt=standard is odd.. It really means return json formatted code. I dug around some more and we have werid complex logic around this parameter. Digging furthur, I think most of the complexity is not needed.

The one thing that I DID change is that before if you did "wt=fake" then you would get JSON back in many places. And in the V2 api's if you did "wt=fake" you would get a 400 back with an error. I think the right think in either of those cases is a 500 server error.

Summary of 63d4284

I've updated the code so that when an invalid/unknown wt parameter is provided, Solr returns a 500 Server Error instead of silently falling back or returning a null writer.

Changes Made to default behavior:

  1. SolrQueryRequest.java (lines 207-222):

    • Added validation that throws a SolrException with SERVER_ERROR (500) when the response writer is not found for the given wt parameter
    • The error message clearly states: "Unknown response writer type: {wt}"
  2. V2ApiIntegrationTest.java:

    • Split the original testWTParam test into two tests:
      • testInvalidWTParamReturnsError - verifies that wt=bleh returns a 500 error with the appropriate message
      • testWTParam - verifies that when no wt is specified, JSON is used by default
  3. TestPrometheusResponseWriter.java:

    • Updated the comment in testUnsupportedMetricsFormat to clarify that unknown wt parameters return a 500 error
    • The test already asserted assertEquals(500, res.get("responseStatus")) which now passes

Solution

Mostly refactoring, except for the big change in 63d4284 which changed the response logic.

Tests

Re ran test

epugh added 3 commits January 27, 2026 13:02
…s to work

Some failing tests for plugins like CborResponseWriter that aren't in the content type --> wt converter.
…t found you get a 500 error.

I think using a bad responsewriter should be an error, and we shoudln't cover it up, or return json...
handlers.init(Collections.emptyMap(), core, modifiedInfos);
handlers.alias(handlers.getDefault(), "");
// Curious if this is actually needed!
// handlers.alias(handlers.getDefault(), "");
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tests all pass!

}
}
// Default to JSON when no Accept header or unrecognized content type
return CommonParams.JSON;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i remain ambivalent about these... maybe okay? I mean, if I do a curl command don't provide wt=json OR the content types, maybe okay? It might be a perfectly nice thign for our users...

public static final String SIMPLE = "simple";
public static final String STANDARD = "standard";
// public static final String MULTIPART = "multipart";
// public static final String FORMDATA = "formdata";
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so many unused statics!

public void testInvalidWTParamReturnsError() throws Exception {
V2Request request = new V2Request.Builder("/c/" + COLL_NAME + "/get/_introspect").build();
// TODO: If possible do this in a better way
// Using an invalid wt parameter should return a 500 error
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the Big Change.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Updates Solr’s response-writer (wt) handling to reduce reliance on the legacy "standard" writer and to fail fast when an unknown response writer is requested.

Changes:

  • Adds stricter wt validation and introduces an Accept-header fallback when wt is absent.
  • Removes/neutralizes legacy "standard" response-writer wiring and adjusts handler aliasing behavior.
  • Updates tests and test utilities to reflect the new error behavior and defaults.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
solr/test-framework/src/java/org/apache/solr/util/TestHarness.java Forces wt=xml in a common local test request path to preserve historical XML expectations.
solr/core/src/test/org/apache/solr/response/TestPrometheusResponseWriter.java Updates expected status for unknown wt to 500.
solr/core/src/test/org/apache/solr/handler/V2ApiIntegrationTest.java Splits wt tests and asserts 500 + message for invalid writer types.
solr/core/src/java/org/apache/solr/servlet/SolrRequestParsers.java Comments out legacy constants/registry code (effectively disabling/removing it).
solr/core/src/java/org/apache/solr/request/SolrQueryRequest.java Adds Accept header → wt mapping and throws 500 for unknown response writers.
solr/core/src/java/org/apache/solr/core/SolrCore.java Removes "standard" alias from default writers and stops setting a default writer.
solr/core/src/java/org/apache/solr/core/RequestHandlers.java Stops aliasing the configured default handler to the empty path.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 14 out of 15 changed files in this pull request and generated 9 comments.

Comments suppressed due to low confidence (1)

solr/core/src/java/org/apache/solr/servlet/SolrRequestParsers.java:121

  • There is a large block of commented-out code in init() referencing removed fields/constants (e.g., parsers, STANDARD, standard). Leaving this dead code around makes the refactor harder to follow and risks it getting stale. Prefer deleting it entirely or replacing it with a brief comment explaining the current design (single StandardRequestParser).

  private static RTimerTree getRequestTimer(HttpServletRequest req) {
    final Object reqTimer = req.getAttribute(REQUEST_TIMER_SERVLET_ATTRIBUTE);
    if (reqTimer instanceof RTimerTree) {
      return ((RTimerTree) reqTimer);
    }

    return new RTimerTree();
  }

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@@ -3131,14 +3131,11 @@ private void initWriters() {

// Initialize with the built defaults
responseWriters.init(defaultWriters, this);
Copy link

Copilot AI Feb 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

initWriters() no longer ensures a default response writer is set on responseWriters. If no <queryResponseWriter default="true"> is defined in solrconfig (e.g., configsets where response writers are only implicit), PluginBag's default (def) can remain null, which breaks default writer resolution and can change the default output unexpectedly. Consider restoring a safe default (e.g., set default to json) when responseWriters.getDefault() is null after init.

Suggested change
responseWriters.init(defaultWriters, this);
responseWriters.init(defaultWriters, this);
// Ensure there is always a default response writer configured.
// If no <queryResponseWriter default="true"> is defined and PluginBag
// did not pick a default, fall back to "json" when available.
if (responseWriters.getDefault() == null) {
QueryResponseWriter jsonWriter = responseWriters.get("json", false);
if (jsonWriter != null) {
responseWriters.setDefault("json");
}
}

Copilot uses AI. Check for mistakes.
Comment on lines +52 to +60
QueryResponseWriter standardWriter = ResponseWritersRegistry.getWriter("json");

// Built-in writers should NOT include extended format writers (csv, geojson, etc.)
// These should all fall back to standard
// I think this standard thing is weird... I think it should throw an exception!
// These should all fall back to json
// I think this json thing is weird... I think it should throw an exception!
assertThat(
"geojson should fall back to standard",
"geojson should fall back to json",
ResponseWritersRegistry.getWriter("geojson"),
is(standardWriter));
is(nullValue()));
Copy link

Copilot AI Feb 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In testBuiltInWriterLimitedSet, the local variable name (standardWriter) and the assertion message/comments say these formats "fall back to json", but the assertion expects nullValue(). Either update the test to assert the intended fallback behavior, or rename/update the comments/messages so they match the new contract (unknown built-in writer returns null).

Copilot uses AI. Check for mistakes.

/**
* Pass in an xml configuration. A null configuration will enable everything with maximum values.
* Pass in a xml configuration. A null configuration will enable everything with maximum values.
Copy link

Copilot AI Feb 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Grammar in this Javadoc is off: "Pass in a xml configuration" should be "Pass in an XML configuration" (and typically XML is capitalized).

Suggested change
* Pass in a xml configuration. A null configuration will enable everything with maximum values.
* Pass in an XML configuration. A null configuration will enable everything with maximum values.

Copilot uses AI. Check for mistakes.
Comment on lines 117 to 119
NamedList<Object> res = cluster.getSolrClient().request(request);
String respString = InputStreamResponseParser.consumeResponseToString(res);

Copy link

Copilot AI Feb 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test asserts on substrings like "500" in the raw response body, which is brittle (error pages/formatting can change). Since you already have the NamedList response from InputStreamResponseParser, consider asserting res.get("responseStatus") == 500 (and then optionally assert the message substring) for a more stable check.

Copilot uses AI. Check for mistakes.
@epugh
Copy link
Contributor Author

epugh commented Feb 4, 2026

@dsmiley assuming all the tests pass, this is ready for merging.

@epugh
Copy link
Contributor Author

epugh commented Feb 4, 2026

@dsmiley assuming all the tests pass, this is ready for review and potentially merging.

prometheusWriter,
ReplicationAPIBase.FILE_STREAM,
new FileStreamResponseWriter());
Map.ofEntries(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice and tidy :-)

protected void logAndFlushAdminRequest(SolrQueryResponse solrResp) throws IOException {
if (solrResp.getToLog().size() > 0) {
// has to come second and in it's own if to keep ./gradlew check happy.
// has to come second and in its own "if" to keep ./gradlew check happy.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minor: I prefer that we don't change source files for out-of-scope reasons that we aren't already touching for in-scope reasons.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, I really struggle with seeing these things and not fixing them. I will try not to do it in the futre. I swear I went through the entire code base and fixed all the typos, and yet I keep finding them.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these changes in-scope?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what's going on here?

note: commented code is typically avoided

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

out-of-scope

@SuppressWarnings({"unchecked"})
public LocalSolrQueryRequest makeRequest(String... q) {
if (q.length == 1) {
args.computeIfAbsent("wt", k -> "xml");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm... how did this end up failing without this?

Clarified the changelog entry by removing redundant information.
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

epugh added 4 commits February 4, 2026 13:50
testSOLR59responseHeaderVersions looks like it tests wt, but the assertQ always sets wt=xml, so it doesn't do anything.   We test qtime and status plenty of other places.   I was confused by USELESS_OUTPUT till I realized it was part of UselessOutputWriter.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants