From a05946a80b23330749548ddf7f811fe45bc77686 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Fri, 16 Oct 2026 00:36:49 +0530 Subject: [PATCH 01/21] rebased with main --- .../solr/client/api/endpoint/ConfigApi.java | 20 ++++- .../solr/handler/SolrConfigHandler.java | 89 +++---------------- .../solr/handler/admin/api/GetConfig.java | 68 +++++++++----- .../solr/handler/admin/api/GetConfigAPI.java | 1 - .../handler/admin/V2ConfigAPIMappingTest.java | 1 - 5 files changed, 76 insertions(+), 103 deletions(-) diff --git a/solr/api/src/java/org/apache/solr/client/api/endpoint/ConfigApi.java b/solr/api/src/java/org/apache/solr/client/api/endpoint/ConfigApi.java index 49a4b018cc99..896142f24aad 100644 --- a/solr/api/src/java/org/apache/solr/client/api/endpoint/ConfigApi.java +++ b/solr/api/src/java/org/apache/solr/client/api/endpoint/ConfigApi.java @@ -70,7 +70,25 @@ ConfigZnodeVersionResponse getZnodeVersion( @Parameter(description = "Expected request-params znode version") int expectedParamsVersion); - // TODO: Keep this regex in sync with GetConfig.MIGRATED_CONFIG_COMPONENTS ("searchComponents" + @GET + @Path("/requestHandlers") + @StoreApiParameters + @Operation( + summary = "Fetch request handlers (including implicit handler)", + tags = {"config"}) + ConfigInfoResponse getRequestHandler( + @PathParam("componentName") @Parameter(description = "Name of the specific request handler") + String component, + @QueryParam("expandParams") + @DefaultValue("false") + @Parameter(description = "Expand request handler useParams and effective parameters") + boolean expandParams, + @QueryParam("meta") + @DefaultValue("false") + @Parameter(description = "Include package metadata (_packageinfo_)") + boolean meta); + + // TODO: Keep this regex in sync with GetConfig.MIGRATED_CONFIG_COMPONENTS // and "queryResponseWriters" here are the external, pluralized names for the internal // "searchComponent"/"queryResponseWriter" sections; see GetConfig#toExternalComponentName) @GET diff --git a/solr/core/src/java/org/apache/solr/handler/SolrConfigHandler.java b/solr/core/src/java/org/apache/solr/handler/SolrConfigHandler.java index 08614a0a4bc6..5d7432ca34c9 100644 --- a/solr/core/src/java/org/apache/solr/handler/SolrConfigHandler.java +++ b/solr/core/src/java/org/apache/solr/handler/SolrConfigHandler.java @@ -21,10 +21,7 @@ import static org.apache.solr.core.ConfigOverlay.NOT_EDITABLE; import static org.apache.solr.core.ConfigOverlay.ZNODEVER; import static org.apache.solr.core.ConfigSetProperties.IMMUTABLE_CONFIGSET_ARG; -import static org.apache.solr.core.PluginInfo.APPENDS; import static org.apache.solr.core.PluginInfo.DEFAULTS; -import static org.apache.solr.core.PluginInfo.INVARIANTS; -import static org.apache.solr.core.RequestParams.USEPARAM; import static org.apache.solr.core.SolrConfig.PluginOpts.REQUIRE_CLASS; import static org.apache.solr.core.SolrConfig.PluginOpts.REQUIRE_NAME; import static org.apache.solr.core.SolrConfig.PluginOpts.REQUIRE_NAME_IN_OVERLAY; @@ -69,7 +66,6 @@ import org.apache.solr.common.cloud.Replica; import org.apache.solr.common.cloud.Slice; import org.apache.solr.common.params.CommonParams; -import org.apache.solr.common.params.MapSolrParams; import org.apache.solr.common.params.ModifiableSolrParams; import org.apache.solr.common.params.SolrParams; import org.apache.solr.common.util.CommandOperation; @@ -97,7 +93,6 @@ import org.apache.solr.security.AuthorizationContext; import org.apache.solr.security.PermissionNameProvider; import org.apache.solr.util.RTimer; -import org.apache.solr.util.SolrPluginUtils; import org.apache.solr.util.plugin.SolrCoreAware; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -221,6 +216,14 @@ private void handleGET() { .getZnodeVersion( req.getParams().getInt(ConfigOverlay.NAME, -1), req.getParams().getInt(RequestParams.NAME, -1))); + } else if (SolrRequestHandler.TYPE.equals(parts.get(1))) { + V2ApiUtils.squashIntoSolrResponseWithoutHeader( + resp, + new GetConfig(req) + .getRequestHandler( + req.getParams().get("componentName"), + req.getParams().getBool("expandParams", false), + req.getParams().getBool("meta", false))); } else if (GetConfig.MIGRATED_CONFIG_COMPONENTS.contains(parts.get(1))) { String componentName = req.getParams().get("componentName"); GetConfig getConfig = new GetConfig(req); @@ -231,7 +234,8 @@ private void handleGET() { : getConfig.getConfigComponentByName( parts.get(1), componentName, req.getParams().getBool("meta", false))); } else { - Map m = getConfigDetails(parts.get(1), req); + Map m = + Utils.convertToMap(req.getCore().getSolrConfig(), new LinkedHashMap<>()); Map val = new LinkedHashMap<>(); val.put(parts.get(1), m.get(parts.get(1))); String componentName = req.getParams().get("componentName"); @@ -245,79 +249,6 @@ private void handleGET() { } } - private Map getConfigDetails(String componentType, SolrQueryRequest req) { - String componentName = componentType == null ? null : req.getParams().get("componentName"); - boolean showParams = req.getParams().getBool("expandParams", false); - Map map = - Utils.convertToMap(this.req.getCore().getSolrConfig(), new LinkedHashMap<>()); - if (componentType != null && !SolrRequestHandler.TYPE.equals(componentType)) return map; - - @SuppressWarnings({"unchecked"}) - Map reqHandlers = - (Map) - map.computeIfAbsent(SolrRequestHandler.TYPE, k -> new LinkedHashMap<>()); - List plugins = this.req.getCore().getImplicitHandlers(); - for (PluginInfo plugin : plugins) { - if (SolrRequestHandler.TYPE.equals(plugin.type)) { - if (!reqHandlers.containsKey(plugin.name)) { - reqHandlers.put(plugin.name, plugin); - } - } - } - if (!showParams) return map; - for (Map.Entry e : reqHandlers.entrySet()) { - if (componentName == null || e.getKey().equals(componentName)) { - Map m = expandUseParams(req, e.getValue()); - e.setValue(m); - } - } - - return map; - } - - @SuppressWarnings({"unchecked"}) - private Map expandUseParams(SolrQueryRequest req, Object plugin) { - - Map pluginInfo = null; - if (plugin instanceof Map) { - pluginInfo = (Map) plugin; - } else if (plugin instanceof PluginInfo) { - pluginInfo = Utils.convertToMap((PluginInfo) plugin, new LinkedHashMap<>()); - } - String useParams = (String) pluginInfo.get(USEPARAM); - String useParamsInReq = req.getOriginalParams().get(USEPARAM); - if (useParams != null || useParamsInReq != null) { - Map m = new LinkedHashMap<>(); - pluginInfo.put("_useParamsExpanded_", m); - List params = new ArrayList<>(); - if (useParams != null) params.addAll(StrUtils.splitSmart(useParams, ',')); - if (useParamsInReq != null) params.addAll(StrUtils.splitSmart(useParamsInReq, ',')); - for (String param : params) { - RequestParams.ParamSet p = - this.req.getCore().getSolrConfig().getRequestParams().getParams(param); - if (p != null) { - m.put(param, p); - } else { - m.put(param, "[NOT AVAILABLE]"); - } - } - - SolrQueryRequest r = req.subRequest(req.getOriginalParams()); - r.getContext().put(USEPARAM, useParams); - NamedList nl = new PluginInfo(SolrRequestHandler.TYPE, pluginInfo).initArgs; - SolrPluginUtils.setDefaults( - r, - getSolrParamsFromNamedList(nl, DEFAULTS), - getSolrParamsFromNamedList(nl, APPENDS), - getSolrParamsFromNamedList(nl, INVARIANTS)); - // SolrParams.wrapDefaults(maskUseParams, req.getParams()) - - MapSolrParams mask = new MapSolrParams(Map.of("componentName", "", "expandParams", "")); - pluginInfo.put("_effectiveParams_", SolrParams.wrapDefaults(mask, r.getParams())); - } - return pluginInfo; - } - private void handlePOST() throws IOException { List ops = ApiBag.readCommands(req.getContentStreams(), resp.getValues()); if (ops == null) return; diff --git a/solr/core/src/java/org/apache/solr/handler/admin/api/GetConfig.java b/solr/core/src/java/org/apache/solr/handler/admin/api/GetConfig.java index 1bc7db362bd9..9bff454fbe12 100644 --- a/solr/core/src/java/org/apache/solr/handler/admin/api/GetConfig.java +++ b/solr/core/src/java/org/apache/solr/handler/admin/api/GetConfig.java @@ -99,7 +99,7 @@ public GetConfig(SolrQueryRequest solrQueryRequest) { @PermissionName(CONFIG_READ_PERM) public ConfigInfoResponse getConfig(boolean expandParams) { final var response = instantiateJerseyResponse(ConfigInfoResponse.class); - response.config = buildConfigMap(solrQueryRequest, expandParams); + response.config = buildConfigMap(expandParams); return response; } @@ -129,13 +129,32 @@ public ConfigZnodeVersionResponse getZnodeVersion( return response; } + @Override + @PermissionName(CONFIG_READ_PERM) + public ConfigInfoResponse getRequestHandler( + String componentName, boolean expandParams, boolean meta) { + final var response = instantiateJerseyResponse(ConfigInfoResponse.class); + + Map configMap = solrConfigAsMap(); + configMap.put( + SolrRequestHandler.TYPE, + requestHandlersWithImplicits(configMap, expandParams, componentName)); + filterByComponentName( + configMap, SolrRequestHandler.TYPE, componentName, meta, solrQueryRequest); + + response.config = jsonSafeCopy(configMap); + return response; + } + @Override @PermissionName(CONFIG_READ_PERM) public ConfigInfoResponse getConfigComponent(String component) { final var response = instantiateJerseyResponse(ConfigInfoResponse.class); - Map section = new LinkedHashMap<>(); - section.put(component, solrConfigAsMap().get(toInternalComponentName(component))); - response.config = jsonSafeCopy(section); + + Map configMap = new LinkedHashMap<>(); + configMap.put(component, solrConfigAsMap().get(toInternalComponentName(component))); + + response.config = jsonSafeCopy(configMap); return response; } @@ -144,10 +163,11 @@ public ConfigInfoResponse getConfigComponent(String component) { public ConfigInfoResponse getConfigComponentByName( String component, String componentName, boolean meta) { final var response = instantiateJerseyResponse(ConfigInfoResponse.class); - Map section = new LinkedHashMap<>(); - section.put(component, solrConfigAsMap().get(toInternalComponentName(component))); - filterByComponentName(section, component, componentName, meta, solrQueryRequest); - response.config = jsonSafeCopy(section); + + Map configMap = new LinkedHashMap<>(); + configMap.put(component, solrConfigAsMap().get(toInternalComponentName(component))); + filterByComponentName(configMap, component, componentName, meta, solrQueryRequest); + response.config = jsonSafeCopy(configMap); return response; } @@ -161,12 +181,12 @@ public ConfigInfoResponse getConfigComponentByName( */ @SuppressWarnings({"unchecked", "rawtypes"}) public static void filterByComponentName( - Map section, + Map configMap, String component, String componentName, boolean meta, SolrQueryRequest req) { - Map pluginNameVsPluginInfo = (Map) section.get(component); + Map pluginNameVsPluginInfo = (Map) configMap.get(component); if (pluginNameVsPluginInfo == null) { return; } @@ -183,7 +203,7 @@ public static void filterByComponentName( Map pluginInfo = o instanceof MapWriter ? new SimpleOrderedMap<>((MapWriter) o) : (Map) o; - section.put( + configMap.put( component, pluginNameVsPluginInfo instanceof MapWriter ? pluginInfo @@ -227,29 +247,35 @@ private NullKeyTolerantMap jsonSafeCopy(Map map) { return jsonSafeCopy; } - @SuppressWarnings({"unchecked"}) - private Map buildConfigMap( - SolrQueryRequest solrQueryRequest, boolean expandParams) { - + private Map buildConfigMap(boolean expandParams) { Map configMap = solrConfigAsMap(); + requestHandlersWithImplicits(configMap, expandParams, null); + return jsonSafeCopy(configMap); + } - Map reqHandlers = + @SuppressWarnings({"unchecked"}) + private Map requestHandlersWithImplicits( + Map configMap, boolean expandParams, String expandOnlyComponentName) { + Map reqHandlersMap = (Map) configMap.computeIfAbsent(SolrRequestHandler.TYPE, k -> new LinkedHashMap<>()); + List plugins = solrQueryRequest.getCore().getImplicitHandlers(); for (PluginInfo plugin : plugins) { - if (SolrRequestHandler.TYPE.equals(plugin.type) && !reqHandlers.containsKey(plugin.name)) { - reqHandlers.put(plugin.name, plugin); + if (SolrRequestHandler.TYPE.equals(plugin.type) && !reqHandlersMap.containsKey(plugin.name)) { + reqHandlersMap.put(plugin.name, plugin); } } if (expandParams) { - for (Map.Entry entry : reqHandlers.entrySet()) { - entry.setValue(expandUseParams(solrQueryRequest, entry.getValue())); + for (Map.Entry entry : reqHandlersMap.entrySet()) { + if (expandOnlyComponentName == null || !expandOnlyComponentName.equals(entry.getKey())) { + entry.setValue(expandUseParams(solrQueryRequest, entry.getValue())); + } } } - return jsonSafeCopy(configMap); + return reqHandlersMap; } @SuppressWarnings({"unchecked", "rawtypes"}) diff --git a/solr/core/src/java/org/apache/solr/handler/admin/api/GetConfigAPI.java b/solr/core/src/java/org/apache/solr/handler/admin/api/GetConfigAPI.java index 808bdf545f42..6cd437911006 100644 --- a/solr/core/src/java/org/apache/solr/handler/admin/api/GetConfigAPI.java +++ b/solr/core/src/java/org/apache/solr/handler/admin/api/GetConfigAPI.java @@ -61,7 +61,6 @@ public void getSingleParamSet(SolrQueryRequest req, SolrQueryResponse rsp) { @EndPoint( path = { "/config/luceneMatchVersion", - "/config/requestHandler", "/config/initParams", "/config/listener", "/config/requestDispatcher", diff --git a/solr/core/src/test/org/apache/solr/handler/admin/V2ConfigAPIMappingTest.java b/solr/core/src/test/org/apache/solr/handler/admin/V2ConfigAPIMappingTest.java index 6e0a2aa6e27a..e7912afa8faa 100644 --- a/solr/core/src/test/org/apache/solr/handler/admin/V2ConfigAPIMappingTest.java +++ b/solr/core/src/test/org/apache/solr/handler/admin/V2ConfigAPIMappingTest.java @@ -49,7 +49,6 @@ public void populateApiBag() { // the API lookup works for a handful of the valid config "components". @Test public void testGetSingleComponentConfig() { - assertAnnotatedApiExistsFor("GET", "/config/requestHandler"); assertAnnotatedApiExistsFor("GET", "/config/jmx"); assertAnnotatedApiExistsFor("GET", "/config/requestDispatcher"); assertAnnotatedApiExistsFor("GET", "/config/luceneMatchVersion"); From 1efb6026f4e237217a1d27f2b20b8461f341732e Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Fri, 16 Oct 2026 01:34:37 +0530 Subject: [PATCH 02/21] queryparam --- .../java/org/apache/solr/client/api/endpoint/ConfigApi.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/solr/api/src/java/org/apache/solr/client/api/endpoint/ConfigApi.java b/solr/api/src/java/org/apache/solr/client/api/endpoint/ConfigApi.java index 896142f24aad..e134fa25b5ea 100644 --- a/solr/api/src/java/org/apache/solr/client/api/endpoint/ConfigApi.java +++ b/solr/api/src/java/org/apache/solr/client/api/endpoint/ConfigApi.java @@ -77,7 +77,8 @@ ConfigZnodeVersionResponse getZnodeVersion( summary = "Fetch request handlers (including implicit handler)", tags = {"config"}) ConfigInfoResponse getRequestHandler( - @PathParam("componentName") @Parameter(description = "Name of the specific request handler") + @QueryParam("componentName") + @Parameter(description = "Name of the specific request handler") String component, @QueryParam("expandParams") @DefaultValue("false") From 5baa8ab3b81d8028402f25926ab7e1bcfc3bc2c0 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Fri, 16 Oct 2026 01:37:09 +0530 Subject: [PATCH 03/21] minor --- .../src/java/org/apache/solr/client/api/endpoint/ConfigApi.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/solr/api/src/java/org/apache/solr/client/api/endpoint/ConfigApi.java b/solr/api/src/java/org/apache/solr/client/api/endpoint/ConfigApi.java index e134fa25b5ea..76787c45cca8 100644 --- a/solr/api/src/java/org/apache/solr/client/api/endpoint/ConfigApi.java +++ b/solr/api/src/java/org/apache/solr/client/api/endpoint/ConfigApi.java @@ -71,7 +71,7 @@ ConfigZnodeVersionResponse getZnodeVersion( int expectedParamsVersion); @GET - @Path("/requestHandlers") + @Path("/requestHandler") @StoreApiParameters @Operation( summary = "Fetch request handlers (including implicit handler)", From 6c10a1450e5066a09bcccfdb140b9b7cad167684 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Fri, 16 Oct 2026 01:43:38 +0530 Subject: [PATCH 04/21] corrections --- .../org/apache/solr/handler/admin/api/GetConfig.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/solr/core/src/java/org/apache/solr/handler/admin/api/GetConfig.java b/solr/core/src/java/org/apache/solr/handler/admin/api/GetConfig.java index 9bff454fbe12..560137eaaec9 100644 --- a/solr/core/src/java/org/apache/solr/handler/admin/api/GetConfig.java +++ b/solr/core/src/java/org/apache/solr/handler/admin/api/GetConfig.java @@ -135,12 +135,14 @@ public ConfigInfoResponse getRequestHandler( String componentName, boolean expandParams, boolean meta) { final var response = instantiateJerseyResponse(ConfigInfoResponse.class); - Map configMap = solrConfigAsMap(); + Map configMap = new LinkedHashMap<>(); configMap.put( SolrRequestHandler.TYPE, - requestHandlersWithImplicits(configMap, expandParams, componentName)); - filterByComponentName( - configMap, SolrRequestHandler.TYPE, componentName, meta, solrQueryRequest); + requestHandlersWithImplicits(solrConfigAsMap(), expandParams, componentName)); + if (componentName != null) { + filterByComponentName( + configMap, SolrRequestHandler.TYPE, componentName, meta, solrQueryRequest); + } response.config = jsonSafeCopy(configMap); return response; From b02cf83dfeb48da83aed98fa82c7f9671e543af0 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Fri, 16 Oct 2026 01:52:23 +0530 Subject: [PATCH 05/21] minor fix --- .../src/java/org/apache/solr/handler/admin/api/GetConfig.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/solr/core/src/java/org/apache/solr/handler/admin/api/GetConfig.java b/solr/core/src/java/org/apache/solr/handler/admin/api/GetConfig.java index 560137eaaec9..cddbec5cdc59 100644 --- a/solr/core/src/java/org/apache/solr/handler/admin/api/GetConfig.java +++ b/solr/core/src/java/org/apache/solr/handler/admin/api/GetConfig.java @@ -271,7 +271,7 @@ private Map requestHandlersWithImplicits( if (expandParams) { for (Map.Entry entry : reqHandlersMap.entrySet()) { - if (expandOnlyComponentName == null || !expandOnlyComponentName.equals(entry.getKey())) { + if (expandOnlyComponentName == null || expandOnlyComponentName.equals(entry.getKey())) { entry.setValue(expandUseParams(solrQueryRequest, entry.getValue())); } } From 4e159cda07f8ad7e3895e483a64c10a8196ecb74 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Fri, 16 Oct 2026 01:56:14 +0530 Subject: [PATCH 06/21] added cl --- .../unreleased/SOLR-16396-config-requestHandler.yml | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 changelog/unreleased/SOLR-16396-config-requestHandler.yml diff --git a/changelog/unreleased/SOLR-16396-config-requestHandler.yml b/changelog/unreleased/SOLR-16396-config-requestHandler.yml new file mode 100644 index 000000000000..53f2b8f1b792 --- /dev/null +++ b/changelog/unreleased/SOLR-16396-config-requestHandler.yml @@ -0,0 +1,9 @@ +title: > + Migrate GET /config/requestHandler to JAX-RS +type: changed +authors: + - name: Jalaz Kumar + nick: jaykay12 +links: + - name: SOLR-16396 + url: https://issues.apache.org/jira/browse/SOLR-16396 From 05d0a9bb646f52f1b2b53063670bcdfa28e7d99c Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Fri, 16 Oct 2026 02:32:54 +0530 Subject: [PATCH 07/21] added tests --- .../solr/client/api/endpoint/ConfigApi.java | 2 +- .../solr/handler/admin/api/GetConfigTest.java | 85 +++++++++++++++++++ 2 files changed, 86 insertions(+), 1 deletion(-) diff --git a/solr/api/src/java/org/apache/solr/client/api/endpoint/ConfigApi.java b/solr/api/src/java/org/apache/solr/client/api/endpoint/ConfigApi.java index 76787c45cca8..bb4b6a1cbc7a 100644 --- a/solr/api/src/java/org/apache/solr/client/api/endpoint/ConfigApi.java +++ b/solr/api/src/java/org/apache/solr/client/api/endpoint/ConfigApi.java @@ -89,7 +89,7 @@ ConfigInfoResponse getRequestHandler( @Parameter(description = "Include package metadata (_packageinfo_)") boolean meta); - // TODO: Keep this regex in sync with GetConfig.MIGRATED_CONFIG_COMPONENTS + // TODO: Keep this regex in sync with GetConfig.MIGRATED_CONFIG_COMPONENTS ("searchComponents" // and "queryResponseWriters" here are the external, pluralized names for the internal // "searchComponent"/"queryResponseWriter" sections; see GetConfig#toExternalComponentName) @GET diff --git a/solr/core/src/test/org/apache/solr/handler/admin/api/GetConfigTest.java b/solr/core/src/test/org/apache/solr/handler/admin/api/GetConfigTest.java index 504fe7ecb5e7..d0415fc21cf4 100644 --- a/solr/core/src/test/org/apache/solr/handler/admin/api/GetConfigTest.java +++ b/solr/core/src/test/org/apache/solr/handler/admin/api/GetConfigTest.java @@ -23,6 +23,7 @@ import org.apache.solr.client.api.model.IndexType; import org.apache.solr.client.solrj.RemoteSolrException; import org.apache.solr.client.solrj.request.ConfigApi; +import org.apache.solr.request.SolrRequestHandler; import org.apache.solr.util.ExternalPaths; import org.apache.solr.util.SolrJettyTestRule; import org.junit.BeforeClass; @@ -83,6 +84,90 @@ public void testGetZnodeVersionFromCore() throws Exception { assertTrue(response.znodeVersion.params >= -1); } + @Test + @SuppressWarnings("unchecked") + public void testGetRequestHandlersFromCore() throws Exception { + var request = new ConfigApi.GetRequestHandler(IndexType.CORE, CORE_NAME); + var response = request.process(solrTestRule.getSolrClient(CORE_NAME)); + + assertNotNull(response); + assertNull(response.error); + assertNotNull(response.config); + assertEquals(1, response.config.size()); + + Map configSection = + (Map) response.config.get(SolrRequestHandler.TYPE); + assertNotNull(configSection); + assertTrue(configSection.containsKey("/select")); + assertTrue(configSection.containsKey("/admin/ping")); + } + + @Test + @SuppressWarnings("unchecked") + public void testGetRequestHandlersFilteredByNameFromCore() throws Exception { + var request = new ConfigApi.GetRequestHandler(IndexType.CORE, CORE_NAME); + request.setComponentName("/select"); + var response = request.process(solrTestRule.getSolrClient(CORE_NAME)); + + assertNotNull(response); + assertNull(response.error); + assertEquals(1, response.config.size()); + + Map configSection = + (Map) response.config.get(SolrRequestHandler.TYPE); + assertNotNull(configSection); + assertTrue(configSection.containsKey("/select")); + + Map select = (Map) configSection.get("/select"); + assertEquals("solr.SearchHandler", select.get("class")); + } + + @Test + @SuppressWarnings("unchecked") + public void testGetRequestHandlersExpandParamsExpandsNamedHandler() throws Exception { + var request = new ConfigApi.GetRequestHandler(IndexType.CORE, CORE_NAME); + request.setComponentName("/admin/ping"); + request.setExpandParams(true); + var response = request.process(solrTestRule.getSolrClient(CORE_NAME)); + + assertNotNull(response); + assertNull(response.error); + assertEquals(1, response.config.size()); + + Map configSection = + (Map) response.config.get(SolrRequestHandler.TYPE); + + Map ping = (Map) configSection.get("/admin/ping"); + assertNotNull(ping.get("_useParamsExpanded_")); + Map expanded = (Map) ping.get("_useParamsExpanded_"); + assertEquals("[NOT AVAILABLE]", expanded.get("_ADMIN_PING")); + } + + @Test + @SuppressWarnings("unchecked") + public void testGetRequestHandlersOmitsExpandedParamsByDefault() throws Exception { + var request = new ConfigApi.GetRequestHandler(IndexType.CORE, CORE_NAME); + request.setComponentName("/admin/ping"); + var response = request.process(solrTestRule.getSolrClient(CORE_NAME)); + + Map configSection = + (Map) response.config.get(SolrRequestHandler.TYPE); + + Map ping = (Map) configSection.get("/admin/ping"); + assertFalse(ping.containsKey("_useParamsExpanded_")); + } + + @Test + public void testGetRequestHandlersByUnknownNameReturnsNotFound() throws Exception { + var request = new ConfigApi.GetRequestHandler(IndexType.CORE, CORE_NAME); + request.setComponentName("/randomHandler"); + final RemoteSolrException exception = + assertThrows( + RemoteSolrException.class, + () -> request.process(solrTestRule.getSolrClient(CORE_NAME))); + assertEquals(404, exception.code()); + } + @Test public void testGetConfigComponentFromCore() throws Exception { for (String component : GetConfig.MIGRATED_CONFIG_COMPONENTS) { From a7618b82549544a4793512c85257c3eff48eb908 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Fri, 16 Oct 2026 12:26:09 +0530 Subject: [PATCH 08/21] cl minor --- changelog/unreleased/SOLR-16396-config-requestHandler.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelog/unreleased/SOLR-16396-config-requestHandler.yml b/changelog/unreleased/SOLR-16396-config-requestHandler.yml index 53f2b8f1b792..988571917264 100644 --- a/changelog/unreleased/SOLR-16396-config-requestHandler.yml +++ b/changelog/unreleased/SOLR-16396-config-requestHandler.yml @@ -1,4 +1,4 @@ -title: > +title: Migrate GET /config/requestHandler to JAX-RS type: changed authors: From e6b2f0734e0bc9dc441d907c10cc876bf9058ac3 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Fri, 16 Oct 2026 18:17:08 +0530 Subject: [PATCH 09/21] changes --- .../apache/solr/client/api/endpoint/ConfigApi.java | 2 +- .../org/apache/solr/handler/SolrConfigHandler.java | 3 ++- .../apache/solr/handler/admin/api/GetConfig.java | 7 ++++--- .../test/org/apache/solr/cli/PackageToolTest.java | 4 ++-- .../solr/handler/admin/api/GetConfigTest.java | 14 +++++--------- 5 files changed, 14 insertions(+), 16 deletions(-) diff --git a/solr/api/src/java/org/apache/solr/client/api/endpoint/ConfigApi.java b/solr/api/src/java/org/apache/solr/client/api/endpoint/ConfigApi.java index bb4b6a1cbc7a..0f3f64868b8c 100644 --- a/solr/api/src/java/org/apache/solr/client/api/endpoint/ConfigApi.java +++ b/solr/api/src/java/org/apache/solr/client/api/endpoint/ConfigApi.java @@ -71,7 +71,7 @@ ConfigZnodeVersionResponse getZnodeVersion( int expectedParamsVersion); @GET - @Path("/requestHandler") + @Path("/requestHandlers") @StoreApiParameters @Operation( summary = "Fetch request handlers (including implicit handler)", diff --git a/solr/core/src/java/org/apache/solr/handler/SolrConfigHandler.java b/solr/core/src/java/org/apache/solr/handler/SolrConfigHandler.java index 5d7432ca34c9..1aeed97cd59d 100644 --- a/solr/core/src/java/org/apache/solr/handler/SolrConfigHandler.java +++ b/solr/core/src/java/org/apache/solr/handler/SolrConfigHandler.java @@ -25,6 +25,7 @@ import static org.apache.solr.core.SolrConfig.PluginOpts.REQUIRE_CLASS; import static org.apache.solr.core.SolrConfig.PluginOpts.REQUIRE_NAME; import static org.apache.solr.core.SolrConfig.PluginOpts.REQUIRE_NAME_IN_OVERLAY; +import static org.apache.solr.handler.admin.api.GetConfig.REQUEST_HANDLERS; import static org.apache.solr.schema.FieldType.CLASS_NAME; import java.io.IOException; @@ -216,7 +217,7 @@ private void handleGET() { .getZnodeVersion( req.getParams().getInt(ConfigOverlay.NAME, -1), req.getParams().getInt(RequestParams.NAME, -1))); - } else if (SolrRequestHandler.TYPE.equals(parts.get(1))) { + } else if (REQUEST_HANDLERS.equals(parts.get(1))) { V2ApiUtils.squashIntoSolrResponseWithoutHeader( resp, new GetConfig(req) diff --git a/solr/core/src/java/org/apache/solr/handler/admin/api/GetConfig.java b/solr/core/src/java/org/apache/solr/handler/admin/api/GetConfig.java index cddbec5cdc59..c444563c4f67 100644 --- a/solr/core/src/java/org/apache/solr/handler/admin/api/GetConfig.java +++ b/solr/core/src/java/org/apache/solr/handler/admin/api/GetConfig.java @@ -68,6 +68,8 @@ public class GetConfig extends JerseyResource implements ConfigApi.Get { "searchComponent", "queryResponseWriter"); + public static final String REQUEST_HANDLERS = "requestHandlers"; + // v2-only renames: external (URL/response-key) component name -> internal SolrConfig section // name. v1's GET /config/{component} keeps using the internal names unchanged. private static final Map EXTERNAL_TO_INTERNAL_COMPONENT_NAME = @@ -137,11 +139,10 @@ public ConfigInfoResponse getRequestHandler( Map configMap = new LinkedHashMap<>(); configMap.put( - SolrRequestHandler.TYPE, + REQUEST_HANDLERS, requestHandlersWithImplicits(solrConfigAsMap(), expandParams, componentName)); if (componentName != null) { - filterByComponentName( - configMap, SolrRequestHandler.TYPE, componentName, meta, solrQueryRequest); + filterByComponentName(configMap, REQUEST_HANDLERS, componentName, meta, solrQueryRequest); } response.config = jsonSafeCopy(configMap); diff --git a/solr/core/src/test/org/apache/solr/cli/PackageToolTest.java b/solr/core/src/test/org/apache/solr/cli/PackageToolTest.java index a919b30555b7..312509746916 100644 --- a/solr/core/src/test/org/apache/solr/cli/PackageToolTest.java +++ b/solr/core/src/test/org/apache/solr/cli/PackageToolTest.java @@ -320,9 +320,9 @@ void assertPackageVersion( testForResponseElement( cluster.getJettySolrRunner(0).getBaseUrl().toString() + "/" + collection, - "/config/requestHandler?componentName=" + component + "&meta=true", + "/config/requestHandlers?componentName=" + component + "&meta=true", credentials, - Arrays.asList("config", "requestHandler", component, "_packageinfo_", "version"), + Arrays.asList("config", "requestHandlers", component, "_packageinfo_", "version"), componentVersion); } diff --git a/solr/core/src/test/org/apache/solr/handler/admin/api/GetConfigTest.java b/solr/core/src/test/org/apache/solr/handler/admin/api/GetConfigTest.java index d0415fc21cf4..ed11ee4c2177 100644 --- a/solr/core/src/test/org/apache/solr/handler/admin/api/GetConfigTest.java +++ b/solr/core/src/test/org/apache/solr/handler/admin/api/GetConfigTest.java @@ -17,13 +17,13 @@ package org.apache.solr.handler.admin.api; import static org.apache.solr.core.CoreContainer.ALLOW_PATHS_SYSPROP; +import static org.apache.solr.handler.admin.api.GetConfig.REQUEST_HANDLERS; import java.util.Map; import org.apache.solr.SolrTestCase; import org.apache.solr.client.api.model.IndexType; import org.apache.solr.client.solrj.RemoteSolrException; import org.apache.solr.client.solrj.request.ConfigApi; -import org.apache.solr.request.SolrRequestHandler; import org.apache.solr.util.ExternalPaths; import org.apache.solr.util.SolrJettyTestRule; import org.junit.BeforeClass; @@ -95,8 +95,7 @@ public void testGetRequestHandlersFromCore() throws Exception { assertNotNull(response.config); assertEquals(1, response.config.size()); - Map configSection = - (Map) response.config.get(SolrRequestHandler.TYPE); + Map configSection = (Map) response.config.get(REQUEST_HANDLERS); assertNotNull(configSection); assertTrue(configSection.containsKey("/select")); assertTrue(configSection.containsKey("/admin/ping")); @@ -113,8 +112,7 @@ public void testGetRequestHandlersFilteredByNameFromCore() throws Exception { assertNull(response.error); assertEquals(1, response.config.size()); - Map configSection = - (Map) response.config.get(SolrRequestHandler.TYPE); + Map configSection = (Map) response.config.get(REQUEST_HANDLERS); assertNotNull(configSection); assertTrue(configSection.containsKey("/select")); @@ -134,8 +132,7 @@ public void testGetRequestHandlersExpandParamsExpandsNamedHandler() throws Excep assertNull(response.error); assertEquals(1, response.config.size()); - Map configSection = - (Map) response.config.get(SolrRequestHandler.TYPE); + Map configSection = (Map) response.config.get(REQUEST_HANDLERS); Map ping = (Map) configSection.get("/admin/ping"); assertNotNull(ping.get("_useParamsExpanded_")); @@ -150,8 +147,7 @@ public void testGetRequestHandlersOmitsExpandedParamsByDefault() throws Exceptio request.setComponentName("/admin/ping"); var response = request.process(solrTestRule.getSolrClient(CORE_NAME)); - Map configSection = - (Map) response.config.get(SolrRequestHandler.TYPE); + Map configSection = (Map) response.config.get(REQUEST_HANDLERS); Map ping = (Map) configSection.get("/admin/ping"); assertFalse(ping.containsKey("_useParamsExpanded_")); From 061c96605767d56771fc30003a0e487f32285450 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Fri, 16 Oct 2026 18:30:18 +0530 Subject: [PATCH 10/21] fix --- .../src/java/org/apache/solr/handler/SolrConfigHandler.java | 4 ++-- .../src/java/org/apache/solr/handler/admin/api/GetConfig.java | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/solr/core/src/java/org/apache/solr/handler/SolrConfigHandler.java b/solr/core/src/java/org/apache/solr/handler/SolrConfigHandler.java index 1aeed97cd59d..2309f409a9c6 100644 --- a/solr/core/src/java/org/apache/solr/handler/SolrConfigHandler.java +++ b/solr/core/src/java/org/apache/solr/handler/SolrConfigHandler.java @@ -25,7 +25,7 @@ import static org.apache.solr.core.SolrConfig.PluginOpts.REQUIRE_CLASS; import static org.apache.solr.core.SolrConfig.PluginOpts.REQUIRE_NAME; import static org.apache.solr.core.SolrConfig.PluginOpts.REQUIRE_NAME_IN_OVERLAY; -import static org.apache.solr.handler.admin.api.GetConfig.REQUEST_HANDLERS; +import static org.apache.solr.handler.admin.api.GetConfig.REQUEST_HANDLER_APIs; import static org.apache.solr.schema.FieldType.CLASS_NAME; import java.io.IOException; @@ -217,7 +217,7 @@ private void handleGET() { .getZnodeVersion( req.getParams().getInt(ConfigOverlay.NAME, -1), req.getParams().getInt(RequestParams.NAME, -1))); - } else if (REQUEST_HANDLERS.equals(parts.get(1))) { + } else if (REQUEST_HANDLER_APIs.contains(parts.get(1))) { V2ApiUtils.squashIntoSolrResponseWithoutHeader( resp, new GetConfig(req) diff --git a/solr/core/src/java/org/apache/solr/handler/admin/api/GetConfig.java b/solr/core/src/java/org/apache/solr/handler/admin/api/GetConfig.java index c444563c4f67..13a2be1cf685 100644 --- a/solr/core/src/java/org/apache/solr/handler/admin/api/GetConfig.java +++ b/solr/core/src/java/org/apache/solr/handler/admin/api/GetConfig.java @@ -69,6 +69,7 @@ public class GetConfig extends JerseyResource implements ConfigApi.Get { "queryResponseWriter"); public static final String REQUEST_HANDLERS = "requestHandlers"; + public static final Set REQUEST_HANDLER_APIs = Set.of(SolrRequestHandler.TYPE, REQUEST_HANDLERS); // v2-only renames: external (URL/response-key) component name -> internal SolrConfig section // name. v1's GET /config/{component} keeps using the internal names unchanged. From 13dd067db62862fc8e2289cf91837785a8d8aeb6 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Fri, 16 Oct 2026 18:45:37 +0530 Subject: [PATCH 11/21] fix for v1 consistency --- .../org/apache/solr/handler/SolrConfigHandler.java | 1 + .../apache/solr/handler/admin/api/GetConfig.java | 13 +++++++++---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/solr/core/src/java/org/apache/solr/handler/SolrConfigHandler.java b/solr/core/src/java/org/apache/solr/handler/SolrConfigHandler.java index 2309f409a9c6..83f76e771df1 100644 --- a/solr/core/src/java/org/apache/solr/handler/SolrConfigHandler.java +++ b/solr/core/src/java/org/apache/solr/handler/SolrConfigHandler.java @@ -222,6 +222,7 @@ private void handleGET() { resp, new GetConfig(req) .getRequestHandler( + parts.get(1), req.getParams().get("componentName"), req.getParams().getBool("expandParams", false), req.getParams().getBool("meta", false))); diff --git a/solr/core/src/java/org/apache/solr/handler/admin/api/GetConfig.java b/solr/core/src/java/org/apache/solr/handler/admin/api/GetConfig.java index 13a2be1cf685..5b10765e4c06 100644 --- a/solr/core/src/java/org/apache/solr/handler/admin/api/GetConfig.java +++ b/solr/core/src/java/org/apache/solr/handler/admin/api/GetConfig.java @@ -69,7 +69,8 @@ public class GetConfig extends JerseyResource implements ConfigApi.Get { "queryResponseWriter"); public static final String REQUEST_HANDLERS = "requestHandlers"; - public static final Set REQUEST_HANDLER_APIs = Set.of(SolrRequestHandler.TYPE, REQUEST_HANDLERS); + public static final Set REQUEST_HANDLER_APIs = + Set.of(SolrRequestHandler.TYPE, REQUEST_HANDLERS); // v2-only renames: external (URL/response-key) component name -> internal SolrConfig section // name. v1's GET /config/{component} keeps using the internal names unchanged. @@ -136,14 +137,18 @@ public ConfigZnodeVersionResponse getZnodeVersion( @PermissionName(CONFIG_READ_PERM) public ConfigInfoResponse getRequestHandler( String componentName, boolean expandParams, boolean meta) { + return getRequestHandler(REQUEST_HANDLERS, componentName, expandParams, meta); + } + + public ConfigInfoResponse getRequestHandler( + String sectionName, String componentName, boolean expandParams, boolean meta) { final var response = instantiateJerseyResponse(ConfigInfoResponse.class); Map configMap = new LinkedHashMap<>(); configMap.put( - REQUEST_HANDLERS, - requestHandlersWithImplicits(solrConfigAsMap(), expandParams, componentName)); + sectionName, requestHandlersWithImplicits(solrConfigAsMap(), expandParams, componentName)); if (componentName != null) { - filterByComponentName(configMap, REQUEST_HANDLERS, componentName, meta, solrQueryRequest); + filterByComponentName(configMap, sectionName, componentName, meta, solrQueryRequest); } response.config = jsonSafeCopy(configMap); From 1291fff8c574cc7ec4d33576024d450be0225bda Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Fri, 16 Oct 2026 21:12:28 +0530 Subject: [PATCH 12/21] test fixes --- changelog/unreleased/SOLR-16396-config-requestHandler.yml | 5 +++-- .../solr/question-answer-repository/repository.json | 4 ++-- .../solr/cli/packagemanager/TestPackageManager.java | 2 +- .../modules/configuration-guide/pages/config-api.adoc | 8 ++++---- .../pages/implicit-requesthandlers.adoc | 4 ++-- 5 files changed, 12 insertions(+), 11 deletions(-) diff --git a/changelog/unreleased/SOLR-16396-config-requestHandler.yml b/changelog/unreleased/SOLR-16396-config-requestHandler.yml index 988571917264..a860843da618 100644 --- a/changelog/unreleased/SOLR-16396-config-requestHandler.yml +++ b/changelog/unreleased/SOLR-16396-config-requestHandler.yml @@ -1,5 +1,6 @@ -title: - Migrate GET /config/requestHandler to JAX-RS +title: > + Migrate GET /config/requestHandler to JAX-RS; V2 path and response key + are now plural requestHandlers (V1 unchanged) type: changed authors: - name: Jalaz Kumar diff --git a/solr/core/src/test-files/solr/question-answer-repository/repository.json b/solr/core/src/test-files/solr/question-answer-repository/repository.json index 05fad9059784..bcfe7779ca3f 100644 --- a/solr/core/src/test-files/solr/question-answer-repository/repository.json +++ b/solr/core/src/test-files/solr/question-answer-repository/repository.json @@ -28,9 +28,9 @@ "method": "POST" }, "verify-command": { - "path": "/api/collections/${collection}/config/requestHandler?componentName=${RH-HANDLER-PATH}&meta=true", + "path": "/api/collections/${collection}/config/requestHandlers?componentName=${RH-HANDLER-PATH}&meta=true", "method": "GET", - "condition": "$['config'].['requestHandler'].['${RH-HANDLER-PATH}'].['_packageinfo_'].['version']", + "condition": "$['config'].['requestHandlers'].['${RH-HANDLER-PATH}'].['_packageinfo_'].['version']", "expected": "${package-version}" } } diff --git a/solr/core/src/test/org/apache/solr/cli/packagemanager/TestPackageManager.java b/solr/core/src/test/org/apache/solr/cli/packagemanager/TestPackageManager.java index 2793af1641d7..825bd3b5a3c5 100644 --- a/solr/core/src/test/org/apache/solr/cli/packagemanager/TestPackageManager.java +++ b/solr/core/src/test/org/apache/solr/cli/packagemanager/TestPackageManager.java @@ -60,7 +60,7 @@ public void testWrongVerificationJPathIsThrown() throws IOException { plugin.verifyCommand = new SolrPackage.Command(); plugin.verifyCommand.method = "GET"; plugin.verifyCommand.path = /*"/api*/ - "/collections/" + COLLECTION_NAME + "/config/requestHandler"; + "/collections/" + COLLECTION_NAME + "/config/requestHandlers"; plugin.verifyCommand.condition = "&[no_quotes_error_jpath]"; manager.verify( new SolrPackageInstance( diff --git a/solr/solr-ref-guide/modules/configuration-guide/pages/config-api.adoc b/solr/solr-ref-guide/modules/configuration-guide/pages/config-api.adoc index 38981e7caf69..01c043ae6a63 100644 --- a/solr/solr-ref-guide/modules/configuration-guide/pages/config-api.adoc +++ b/solr/solr-ref-guide/modules/configuration-guide/pages/config-api.adoc @@ -109,7 +109,7 @@ V2 API:: ==== [source,bash] ---- -http://localhost:8983/api/collections/techproducts/config/requestHandler +http://localhost:8983/api/collections/techproducts/config/requestHandlers ---- ==== ====== @@ -119,7 +119,7 @@ To see the configuration for implicit request handlers, add `expandParams=true` See the documentation for implicit request handlers linked above for examples using this command. The available top-level sections that can be added as path parameters are: `query`, `requestHandler`, `searchComponent`, `updateHandler`, `queryResponseWriter`, `initParams`, `znodeVersion`, `listener`, `directoryFactory`, `indexConfig`, and `codecFactory`. -In the V2 API, `searchComponent` and `queryResponseWriter` are exposed under the pluralized names `searchComponents` and `queryResponseWriters` instead. +In the V2 API, `requestHandler`, `searchComponent` and `queryResponseWriter` are exposed under the pluralized names `requestHandlers`, `searchComponents` and `queryResponseWriters` instead (including the response JSON key). To further restrict the request to a single component within a top-level section, use the `componentName` request parameter. @@ -140,12 +140,12 @@ V2 API:: ==== [source,bash] ---- -http://localhost:8983/api/collections/techproducts/config/requestHandler?componentName=/select +http://localhost:8983/api/collections/techproducts/config/requestHandlers?componentName=/select ---- ==== ====== -The output of this command will look similar to: +The output of this command will look similar to(V1 nests under `requestHandler`; V2 under `requestHandlers`): [source,json] ---- diff --git a/solr/solr-ref-guide/modules/configuration-guide/pages/implicit-requesthandlers.adoc b/solr/solr-ref-guide/modules/configuration-guide/pages/implicit-requesthandlers.adoc index 0aad010ddc92..67948d8f1446 100644 --- a/solr/solr-ref-guide/modules/configuration-guide/pages/implicit-requesthandlers.adoc +++ b/solr/solr-ref-guide/modules/configuration-guide/pages/implicit-requesthandlers.adoc @@ -693,12 +693,12 @@ V2 API:: ==== [source,bash] ---- -http://localhost:8983/api/collections/gettingstarted/config/requestHandler?componentName=/export&expandParams=true +http://localhost:8983/api/collections/gettingstarted/config/requestHandlers?componentName=/export&expandParams=true ---- ==== ====== -The response will look similar to: +The response will look similar to (V1 nests under `requestHandler`; V2 nests under `requestHandlers`): [source,json] ---- From 3372ab79ed3556660b50d24790d3e24fa45c6e0d Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Fri, 16 Oct 2026 22:06:31 +0530 Subject: [PATCH 13/21] minor cleanup --- .../src/java/org/apache/solr/handler/SolrConfigHandler.java | 3 +-- .../src/java/org/apache/solr/handler/admin/api/GetConfig.java | 2 -- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/solr/core/src/java/org/apache/solr/handler/SolrConfigHandler.java b/solr/core/src/java/org/apache/solr/handler/SolrConfigHandler.java index 83f76e771df1..2b2080a06737 100644 --- a/solr/core/src/java/org/apache/solr/handler/SolrConfigHandler.java +++ b/solr/core/src/java/org/apache/solr/handler/SolrConfigHandler.java @@ -25,7 +25,6 @@ import static org.apache.solr.core.SolrConfig.PluginOpts.REQUIRE_CLASS; import static org.apache.solr.core.SolrConfig.PluginOpts.REQUIRE_NAME; import static org.apache.solr.core.SolrConfig.PluginOpts.REQUIRE_NAME_IN_OVERLAY; -import static org.apache.solr.handler.admin.api.GetConfig.REQUEST_HANDLER_APIs; import static org.apache.solr.schema.FieldType.CLASS_NAME; import java.io.IOException; @@ -217,7 +216,7 @@ private void handleGET() { .getZnodeVersion( req.getParams().getInt(ConfigOverlay.NAME, -1), req.getParams().getInt(RequestParams.NAME, -1))); - } else if (REQUEST_HANDLER_APIs.contains(parts.get(1))) { + } else if (SolrRequestHandler.TYPE.equals(parts.get(1))) { V2ApiUtils.squashIntoSolrResponseWithoutHeader( resp, new GetConfig(req) diff --git a/solr/core/src/java/org/apache/solr/handler/admin/api/GetConfig.java b/solr/core/src/java/org/apache/solr/handler/admin/api/GetConfig.java index 5b10765e4c06..3f0466d86af6 100644 --- a/solr/core/src/java/org/apache/solr/handler/admin/api/GetConfig.java +++ b/solr/core/src/java/org/apache/solr/handler/admin/api/GetConfig.java @@ -69,8 +69,6 @@ public class GetConfig extends JerseyResource implements ConfigApi.Get { "queryResponseWriter"); public static final String REQUEST_HANDLERS = "requestHandlers"; - public static final Set REQUEST_HANDLER_APIs = - Set.of(SolrRequestHandler.TYPE, REQUEST_HANDLERS); // v2-only renames: external (URL/response-key) component name -> internal SolrConfig section // name. v1's GET /config/{component} keeps using the internal names unchanged. From ba2c8a956396db56d55b11274c86cd015168ee45 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Fri, 16 Oct 2026 22:49:38 +0530 Subject: [PATCH 14/21] todo --- .../src/java/org/apache/solr/client/api/endpoint/ConfigApi.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/solr/api/src/java/org/apache/solr/client/api/endpoint/ConfigApi.java b/solr/api/src/java/org/apache/solr/client/api/endpoint/ConfigApi.java index 0f3f64868b8c..f10026be9249 100644 --- a/solr/api/src/java/org/apache/solr/client/api/endpoint/ConfigApi.java +++ b/solr/api/src/java/org/apache/solr/client/api/endpoint/ConfigApi.java @@ -70,6 +70,8 @@ ConfigZnodeVersionResponse getZnodeVersion( @Parameter(description = "Expected request-params znode version") int expectedParamsVersion); + // TODO: RH names contain '/' (e.g. /select, /update/json), so they cannot be a @PathParam in + // the current design; Keeping filtering via @QueryParam for now. @GET @Path("/requestHandlers") @StoreApiParameters From e84d371856f2f5eed231f58f0a61e71f9f544f48 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Fri, 16 Oct 2026 23:10:40 +0530 Subject: [PATCH 15/21] more tests coverage & strictness --- .../admin/api/GetConfigSolrCloudTest.java | 89 +++++++++++++++++++ .../solr/handler/admin/api/GetConfigTest.java | 25 ++++-- 2 files changed, 105 insertions(+), 9 deletions(-) diff --git a/solr/core/src/test/org/apache/solr/handler/admin/api/GetConfigSolrCloudTest.java b/solr/core/src/test/org/apache/solr/handler/admin/api/GetConfigSolrCloudTest.java index 19b29380afd8..e480e660c2c3 100644 --- a/solr/core/src/test/org/apache/solr/handler/admin/api/GetConfigSolrCloudTest.java +++ b/solr/core/src/test/org/apache/solr/handler/admin/api/GetConfigSolrCloudTest.java @@ -17,14 +17,17 @@ package org.apache.solr.handler.admin.api; import static org.apache.solr.core.CoreContainer.ALLOW_PATHS_SYSPROP; +import static org.apache.solr.handler.admin.api.GetConfig.REQUEST_HANDLERS; import org.apache.solr.client.api.model.IndexType; +import org.apache.solr.client.solrj.RemoteSolrException; import org.apache.solr.client.solrj.request.CollectionAdminRequest; import org.apache.solr.client.solrj.request.ConfigApi; import org.apache.solr.cloud.SolrCloudTestCase; import org.apache.solr.util.ExternalPaths; import org.junit.BeforeClass; import org.junit.Test; +import java.util.Map; /** HTTP tests for fetching the full config via the collection-scoped v2 path. */ public class GetConfigSolrCloudTest extends SolrCloudTestCase { @@ -77,6 +80,92 @@ public void testGetZnodeVersionFromCollection() throws Exception { assertTrue(response.znodeVersion.params >= -1); } + @Test + @SuppressWarnings("unchecked") + public void testGetRequestHandlersFromCollection() throws Exception { + var request = new ConfigApi.GetRequestHandler(IndexType.COLLECTION, COLLECTION_NAME); + var response = request.process(cluster.getSolrClient()); + + assertNotNull(response); + assertNull(response.error); + assertNotNull(response.config); + assertEquals(1, response.config.size()); + assertTrue(response.config.containsKey(REQUEST_HANDLERS)); + + Map configSection = (Map) response.config.get(REQUEST_HANDLERS); + assertNotNull(configSection); + assertTrue(configSection.containsKey("/select")); + assertTrue(configSection.containsKey("/admin/ping")); + } + + @Test + @SuppressWarnings("unchecked") + public void testGetRequestHandlersFilteredByNameFromCollection() throws Exception { + var request = new ConfigApi.GetRequestHandler(IndexType.COLLECTION, COLLECTION_NAME); + request.setComponentName("/select"); + var response = request.process(cluster.getSolrClient()); + + assertNotNull(response); + assertNull(response.error); + assertEquals(1, response.config.size()); + assertTrue(response.config.containsKey(REQUEST_HANDLERS)); + + Map configSection = (Map) response.config.get(REQUEST_HANDLERS); + assertNotNull(configSection); + assertEquals(1, configSection.size()); + assertTrue(configSection.containsKey("/select")); + + Map selectRHSection = (Map) configSection.get("/select"); + assertEquals("/select", selectRHSection.get("name")); + assertEquals("solr.SearchHandler", selectRHSection.get("class")); + } + + @Test + @SuppressWarnings("unchecked") + public void testGetRequestHandlersExpandParamsTrue() throws Exception { + var request = new ConfigApi.GetRequestHandler(IndexType.COLLECTION, COLLECTION_NAME); + request.setComponentName("/admin/ping"); + request.setExpandParams(true); + var response = request.process(cluster.getSolrClient()); + + assertNotNull(response); + assertNull(response.error); + assertEquals(1, response.config.size()); + assertTrue(response.config.containsKey(REQUEST_HANDLERS)); + + Map configSection = (Map) response.config.get(REQUEST_HANDLERS); + + Map pingRHSection = (Map) configSection.get("/admin/ping"); + assertTrue(pingRHSection.containsKey("_useParamsExpanded_")); + assertNotNull(pingRHSection.get("_useParamsExpanded_")); + Map expandedPingRHSection = (Map) pingRHSection.get("_useParamsExpanded_"); + assertEquals("[NOT AVAILABLE]", expandedPingRHSection.get("_ADMIN_PING")); + } + + @Test + @SuppressWarnings("unchecked") + public void testGetRequestHandlersOmitsExpandedParamsByDefault() throws Exception { + var request = new ConfigApi.GetRequestHandler(IndexType.COLLECTION, COLLECTION_NAME); + request.setComponentName("/admin/ping"); + var response = request.process(cluster.getSolrClient()); + + Map configSection = (Map) response.config.get(REQUEST_HANDLERS); + + Map pingRHSection = (Map) configSection.get("/admin/ping"); + assertFalse(pingRHSection.containsKey("_useParamsExpanded_")); + } + + @Test + public void testGetRequestHandlersByUnknownNameReturnsNotFound() throws Exception { + var request = new ConfigApi.GetRequestHandler(IndexType.COLLECTION, COLLECTION_NAME); + request.setComponentName("/randomHandler"); + final RemoteSolrException exception = + assertThrows( + RemoteSolrException.class, + () -> request.process(cluster.getSolrClient())); + assertEquals(404, exception.code()); + } + @Test public void testGetConfigComponentFromCollection() throws Exception { for (String component : GetConfig.MIGRATED_CONFIG_COMPONENTS) { diff --git a/solr/core/src/test/org/apache/solr/handler/admin/api/GetConfigTest.java b/solr/core/src/test/org/apache/solr/handler/admin/api/GetConfigTest.java index ed11ee4c2177..5c0563cc7133 100644 --- a/solr/core/src/test/org/apache/solr/handler/admin/api/GetConfigTest.java +++ b/solr/core/src/test/org/apache/solr/handler/admin/api/GetConfigTest.java @@ -94,11 +94,13 @@ public void testGetRequestHandlersFromCore() throws Exception { assertNull(response.error); assertNotNull(response.config); assertEquals(1, response.config.size()); + assertTrue(response.config.containsKey(REQUEST_HANDLERS)); Map configSection = (Map) response.config.get(REQUEST_HANDLERS); assertNotNull(configSection); assertTrue(configSection.containsKey("/select")); assertTrue(configSection.containsKey("/admin/ping")); + assertTrue(configSection.containsKey("/spell")); } @Test @@ -111,18 +113,21 @@ public void testGetRequestHandlersFilteredByNameFromCore() throws Exception { assertNotNull(response); assertNull(response.error); assertEquals(1, response.config.size()); + assertTrue(response.config.containsKey(REQUEST_HANDLERS)); Map configSection = (Map) response.config.get(REQUEST_HANDLERS); assertNotNull(configSection); + assertEquals(1, configSection.size()); assertTrue(configSection.containsKey("/select")); - Map select = (Map) configSection.get("/select"); - assertEquals("solr.SearchHandler", select.get("class")); + Map selectRHSection = (Map) configSection.get("/select"); + assertEquals("/select", selectRHSection.get("name")); + assertEquals("solr.SearchHandler", selectRHSection.get("class")); } @Test @SuppressWarnings("unchecked") - public void testGetRequestHandlersExpandParamsExpandsNamedHandler() throws Exception { + public void testGetRequestHandlersExpandParamsTrue() throws Exception { var request = new ConfigApi.GetRequestHandler(IndexType.CORE, CORE_NAME); request.setComponentName("/admin/ping"); request.setExpandParams(true); @@ -131,13 +136,15 @@ public void testGetRequestHandlersExpandParamsExpandsNamedHandler() throws Excep assertNotNull(response); assertNull(response.error); assertEquals(1, response.config.size()); + assertTrue(response.config.containsKey(REQUEST_HANDLERS)); Map configSection = (Map) response.config.get(REQUEST_HANDLERS); - Map ping = (Map) configSection.get("/admin/ping"); - assertNotNull(ping.get("_useParamsExpanded_")); - Map expanded = (Map) ping.get("_useParamsExpanded_"); - assertEquals("[NOT AVAILABLE]", expanded.get("_ADMIN_PING")); + Map pingRHSection = (Map) configSection.get("/admin/ping"); + assertTrue(pingRHSection.containsKey("_useParamsExpanded_")); + assertNotNull(pingRHSection.get("_useParamsExpanded_")); + Map expandedPingRHSection = (Map) pingRHSection.get("_useParamsExpanded_"); + assertEquals("[NOT AVAILABLE]", expandedPingRHSection.get("_ADMIN_PING")); } @Test @@ -149,8 +156,8 @@ public void testGetRequestHandlersOmitsExpandedParamsByDefault() throws Exceptio Map configSection = (Map) response.config.get(REQUEST_HANDLERS); - Map ping = (Map) configSection.get("/admin/ping"); - assertFalse(ping.containsKey("_useParamsExpanded_")); + Map pingRHSection = (Map) configSection.get("/admin/ping"); + assertFalse(pingRHSection.containsKey("_useParamsExpanded_")); } @Test From 6fede4cf402781576f36443d977b2e3e1edfa260 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Fri, 16 Oct 2026 23:15:04 +0530 Subject: [PATCH 16/21] minor --- .../apache/solr/handler/admin/api/GetConfigSolrCloudTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/solr/core/src/test/org/apache/solr/handler/admin/api/GetConfigSolrCloudTest.java b/solr/core/src/test/org/apache/solr/handler/admin/api/GetConfigSolrCloudTest.java index e480e660c2c3..a706f4088f82 100644 --- a/solr/core/src/test/org/apache/solr/handler/admin/api/GetConfigSolrCloudTest.java +++ b/solr/core/src/test/org/apache/solr/handler/admin/api/GetConfigSolrCloudTest.java @@ -96,6 +96,7 @@ public void testGetRequestHandlersFromCollection() throws Exception { assertNotNull(configSection); assertTrue(configSection.containsKey("/select")); assertTrue(configSection.containsKey("/admin/ping")); + assertTrue(configSection.containsKey("/graph")); } @Test From c045334e9d43934f07a695af7cbad6b6be504f01 Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Sat, 17 Oct 2026 19:14:04 +0530 Subject: [PATCH 17/21] tidying --- .../solr/handler/admin/api/GetConfigSolrCloudTest.java | 9 ++++----- .../org/apache/solr/handler/admin/api/GetConfigTest.java | 3 ++- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/solr/core/src/test/org/apache/solr/handler/admin/api/GetConfigSolrCloudTest.java b/solr/core/src/test/org/apache/solr/handler/admin/api/GetConfigSolrCloudTest.java index a706f4088f82..29c10ec2a96b 100644 --- a/solr/core/src/test/org/apache/solr/handler/admin/api/GetConfigSolrCloudTest.java +++ b/solr/core/src/test/org/apache/solr/handler/admin/api/GetConfigSolrCloudTest.java @@ -19,6 +19,7 @@ import static org.apache.solr.core.CoreContainer.ALLOW_PATHS_SYSPROP; import static org.apache.solr.handler.admin.api.GetConfig.REQUEST_HANDLERS; +import java.util.Map; import org.apache.solr.client.api.model.IndexType; import org.apache.solr.client.solrj.RemoteSolrException; import org.apache.solr.client.solrj.request.CollectionAdminRequest; @@ -27,7 +28,6 @@ import org.apache.solr.util.ExternalPaths; import org.junit.BeforeClass; import org.junit.Test; -import java.util.Map; /** HTTP tests for fetching the full config via the collection-scoped v2 path. */ public class GetConfigSolrCloudTest extends SolrCloudTestCase { @@ -139,7 +139,8 @@ public void testGetRequestHandlersExpandParamsTrue() throws Exception { Map pingRHSection = (Map) configSection.get("/admin/ping"); assertTrue(pingRHSection.containsKey("_useParamsExpanded_")); assertNotNull(pingRHSection.get("_useParamsExpanded_")); - Map expandedPingRHSection = (Map) pingRHSection.get("_useParamsExpanded_"); + Map expandedPingRHSection = + (Map) pingRHSection.get("_useParamsExpanded_"); assertEquals("[NOT AVAILABLE]", expandedPingRHSection.get("_ADMIN_PING")); } @@ -161,9 +162,7 @@ public void testGetRequestHandlersByUnknownNameReturnsNotFound() throws Exceptio var request = new ConfigApi.GetRequestHandler(IndexType.COLLECTION, COLLECTION_NAME); request.setComponentName("/randomHandler"); final RemoteSolrException exception = - assertThrows( - RemoteSolrException.class, - () -> request.process(cluster.getSolrClient())); + assertThrows(RemoteSolrException.class, () -> request.process(cluster.getSolrClient())); assertEquals(404, exception.code()); } diff --git a/solr/core/src/test/org/apache/solr/handler/admin/api/GetConfigTest.java b/solr/core/src/test/org/apache/solr/handler/admin/api/GetConfigTest.java index 5c0563cc7133..4407845d1554 100644 --- a/solr/core/src/test/org/apache/solr/handler/admin/api/GetConfigTest.java +++ b/solr/core/src/test/org/apache/solr/handler/admin/api/GetConfigTest.java @@ -143,7 +143,8 @@ public void testGetRequestHandlersExpandParamsTrue() throws Exception { Map pingRHSection = (Map) configSection.get("/admin/ping"); assertTrue(pingRHSection.containsKey("_useParamsExpanded_")); assertNotNull(pingRHSection.get("_useParamsExpanded_")); - Map expandedPingRHSection = (Map) pingRHSection.get("_useParamsExpanded_"); + Map expandedPingRHSection = + (Map) pingRHSection.get("_useParamsExpanded_"); assertEquals("[NOT AVAILABLE]", expandedPingRHSection.get("_ADMIN_PING")); } From bc37b68e292c1434e032b69fa9dea97b662ce4c0 Mon Sep 17 00:00:00 2001 From: Eric Pugh Date: Sat, 17 Oct 2026 10:01:01 -0400 Subject: [PATCH 18/21] Fix v2 API 404 when a /config request is proxied to another node Solr forwards a v2 request to the node that actually hosts the target collection using the short "/c/{collection}/..." path alias (see HttpSolrCall#sendRemoteProxy), but Constants.INDEX_PATH_PREFIX's JAX-RS @Path regex only recognized "cores" or "collections", not "c". Any JAX-RS resource built on that prefix therefore 404'd with "Cannot find API for the path" whenever a request needed to be proxied cross-node. Reproduced with a new 2-node test in GetConfigSolrCloudTest that deliberately sends a GET /config/overlay request to the node that does NOT host the collection's only replica, then fixed by accepting "c" as an alias for "collections" in the path regex. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01RzzUgiebQ8ZhhgE2E7ZZU5 --- .../solr/client/api/util/Constants.java | 12 ++++++- .../admin/api/GetConfigSolrCloudTest.java | 34 ++++++++++++++++++- 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/solr/api/src/java/org/apache/solr/client/api/util/Constants.java b/solr/api/src/java/org/apache/solr/client/api/util/Constants.java index 3e3c7443c18f..13f8009fbb41 100644 --- a/solr/api/src/java/org/apache/solr/client/api/util/Constants.java +++ b/solr/api/src/java/org/apache/solr/client/api/util/Constants.java @@ -24,8 +24,18 @@ private Constants() { public static final String INDEX_TYPE_PATH_PARAMETER = "indexType"; public static final String INDEX_NAME_PATH_PARAMETER = "indexName"; + + // "c" is accepted alongside "collections" because Solr internally forwards a v2 request to the + // node actually hosting a collection using the short "/c/{collection}/..." alias (see + // HttpSolrCall#sendRemoteProxy and V2HttpCall's "c"/"collections" handling); without it, any + // JAX-RS resource built on this prefix 404s with "Cannot find API for the path" whenever the + // request has to be proxied to another node. public static final String INDEX_PATH_PREFIX = - "/{" + INDEX_TYPE_PATH_PARAMETER + ":cores|collections}/{" + INDEX_NAME_PATH_PARAMETER + "}"; + "/{" + + INDEX_TYPE_PATH_PARAMETER + + ":cores|collections|c}/{" + + INDEX_NAME_PATH_PARAMETER + + "}"; public static final String CORE_NAME_PATH_PARAMETER = "coreName"; diff --git a/solr/core/src/test/org/apache/solr/handler/admin/api/GetConfigSolrCloudTest.java b/solr/core/src/test/org/apache/solr/handler/admin/api/GetConfigSolrCloudTest.java index 19b29380afd8..8a23c749e1db 100644 --- a/solr/core/src/test/org/apache/solr/handler/admin/api/GetConfigSolrCloudTest.java +++ b/solr/core/src/test/org/apache/solr/handler/admin/api/GetConfigSolrCloudTest.java @@ -19,9 +19,12 @@ import static org.apache.solr.core.CoreContainer.ALLOW_PATHS_SYSPROP; import org.apache.solr.client.api.model.IndexType; +import org.apache.solr.client.solrj.jetty.HttpJettySolrClient; import org.apache.solr.client.solrj.request.CollectionAdminRequest; import org.apache.solr.client.solrj.request.ConfigApi; import org.apache.solr.cloud.SolrCloudTestCase; +import org.apache.solr.common.cloud.Replica; +import org.apache.solr.embedded.JettySolrRunner; import org.apache.solr.util.ExternalPaths; import org.junit.BeforeClass; import org.junit.Test; @@ -34,7 +37,9 @@ public class GetConfigSolrCloudTest extends SolrCloudTestCase { @BeforeClass public static void setupCluster() throws Exception { System.setProperty(ALLOW_PATHS_SYSPROP, ExternalPaths.SERVER_HOME.toAbsolutePath().toString()); - configureCluster(1).addConfig("conf", configset("cloud-minimal")).configure(); + // 2 nodes so that a request can land on a node that does *not* host the collection's only + // replica, forcing Solr to internally proxy the request to the node that does. + configureCluster(2).addConfig("conf", configset("cloud-minimal")).configure(); CollectionAdminRequest.createCollection(COLLECTION_NAME, "conf", 1, 1) .process(cluster.getSolrClient()); } @@ -77,6 +82,33 @@ public void testGetZnodeVersionFromCollection() throws Exception { assertTrue(response.znodeVersion.params >= -1); } + /** + * Reproduces a bug where a v2 "/config" request proxied internally to the node actually hosting + * the collection fails with "Cannot find API for the path", because Solr forwards such requests + * using the short "/c/{collection}/..." alias, but {@code Constants.INDEX_PATH_PREFIX}'s JAX-RS + * {@code @Path} regex only recognizes "cores" or "collections", not "c". + */ + @Test + public void testGetOverlayFromCollectionViaNonHostingNode() throws Exception { + Replica replica = getCollectionState(COLLECTION_NAME).replicaStream().findFirst().orElseThrow(); + JettySolrRunner hostingJetty = cluster.getReplicaJetty(replica); + JettySolrRunner otherJetty = + cluster.getJettySolrRunners().stream() + .filter(jetty -> jetty != hostingJetty) + .findFirst() + .orElseThrow(); + + try (var client = new HttpJettySolrClient.Builder(otherJetty.getBaseUrl().toString()).build()) { + var request = new ConfigApi.GetOverlay(IndexType.COLLECTION, COLLECTION_NAME); + var response = request.process(client); + + assertNotNull(response); + assertNull(response.error); + assertNotNull(response.overlay); + assertTrue(response.overlay.containsKey("znodeVersion")); + } + } + @Test public void testGetConfigComponentFromCollection() throws Exception { for (String component : GetConfig.MIGRATED_CONFIG_COMPONENTS) { From 5b168595944fb182ecd2a67716e53ce4fce23c86 Mon Sep 17 00:00:00 2001 From: Eric Pugh Date: Sat, 17 Oct 2026 11:13:33 -0400 Subject: [PATCH 19/21] Fix ErrorProne ReferenceEquality failure in the new regression test CI builds with -Werror, and errorprone flags comparing JettySolrRunner instances with != instead of .equals(). Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01RzzUgiebQ8ZhhgE2E7ZZU5 --- .../apache/solr/handler/admin/api/GetConfigSolrCloudTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/solr/core/src/test/org/apache/solr/handler/admin/api/GetConfigSolrCloudTest.java b/solr/core/src/test/org/apache/solr/handler/admin/api/GetConfigSolrCloudTest.java index 8a23c749e1db..51ff1504293d 100644 --- a/solr/core/src/test/org/apache/solr/handler/admin/api/GetConfigSolrCloudTest.java +++ b/solr/core/src/test/org/apache/solr/handler/admin/api/GetConfigSolrCloudTest.java @@ -94,7 +94,7 @@ public void testGetOverlayFromCollectionViaNonHostingNode() throws Exception { JettySolrRunner hostingJetty = cluster.getReplicaJetty(replica); JettySolrRunner otherJetty = cluster.getJettySolrRunners().stream() - .filter(jetty -> jetty != hostingJetty) + .filter(jetty -> !jetty.equals(hostingJetty)) .findFirst() .orElseThrow(); From 54d11e2c9015464ee7ef62f8b5b561e3087ce19b Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Mon, 19 Oct 2026 22:18:43 +0530 Subject: [PATCH 20/21] fixed packagetooltest --- .../repository.json | 29 ++++++++++++++++++- .../org/apache/solr/cli/PackageToolTest.java | 4 +-- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/solr/core/src/test-files/solr/question-answer-repository/repository.json b/solr/core/src/test-files/solr/question-answer-repository/repository.json index bcfe7779ca3f..626361d25d5b 100644 --- a/solr/core/src/test-files/solr/question-answer-repository/repository.json +++ b/solr/core/src/test-files/solr/question-answer-repository/repository.json @@ -48,7 +48,34 @@ "url": "question-answer-request-handler-1.1.jar.tmp", "sig": "2PBHV2xBqd+teFpSY322lviCrr6EXB7g1Q7UAZcNsr2qzR+w+sPSyfV4YYeHKHYbMkyw1YBz11Gw/Fdgd1VIOQ==" } - ] + ], + "manifest": { + "version-constraint": ">8", + "plugins": [ + { + "name": "request-handler", + "setup-command": { + "path": "/api/collections/${collection}/config", + "payload": {"add-requesthandler": {"name": "${RH-HANDLER-PATH}", "class": "question-answer:fullstory.QARequestHandler"}}, + "method": "POST" + }, + "uninstall-command": { + "path": "/api/collections/${collection}/config", + "payload": {"delete-requesthandler": "${RH-HANDLER-PATH}"}, + "method": "POST" + }, + "verify-command": { + "path": "/api/collections/${collection}/config/requestHandlers?componentName=${RH-HANDLER-PATH}&meta=true", + "method": "GET", + "condition": "$['config'].['requestHandlers'].['${RH-HANDLER-PATH}'].['_packageinfo_'].['version']", + "expected": "${package-version}" + } + } + ], + "parameter-defaults": { + "RH-HANDLER-PATH": "/mypath" + } + } } ] } diff --git a/solr/core/src/test/org/apache/solr/cli/PackageToolTest.java b/solr/core/src/test/org/apache/solr/cli/PackageToolTest.java index 312509746916..a919b30555b7 100644 --- a/solr/core/src/test/org/apache/solr/cli/PackageToolTest.java +++ b/solr/core/src/test/org/apache/solr/cli/PackageToolTest.java @@ -320,9 +320,9 @@ void assertPackageVersion( testForResponseElement( cluster.getJettySolrRunner(0).getBaseUrl().toString() + "/" + collection, - "/config/requestHandlers?componentName=" + component + "&meta=true", + "/config/requestHandler?componentName=" + component + "&meta=true", credentials, - Arrays.asList("config", "requestHandlers", component, "_packageinfo_", "version"), + Arrays.asList("config", "requestHandler", component, "_packageinfo_", "version"), componentVersion); } From dc409474c575e274bdef2ed7cd677c719c58f6ef Mon Sep 17 00:00:00 2001 From: jaykay12 Date: Mon, 19 Oct 2026 22:28:09 +0530 Subject: [PATCH 21/21] cl --- changelog/unreleased/SOLR-16396-config-requestHandler.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/changelog/unreleased/SOLR-16396-config-requestHandler.yml b/changelog/unreleased/SOLR-16396-config-requestHandler.yml index a860843da618..44164b792c51 100644 --- a/changelog/unreleased/SOLR-16396-config-requestHandler.yml +++ b/changelog/unreleased/SOLR-16396-config-requestHandler.yml @@ -5,6 +5,8 @@ type: changed authors: - name: Jalaz Kumar nick: jaykay12 + - name: Eric Pugh + nick: epugh links: - name: SOLR-16396 url: https://issues.apache.org/jira/browse/SOLR-16396