Skip to content

Commit d5aaf27

Browse files
authored
SOLR-17872: Remove org.apache.http dependency from compile scope (#3498)
Solr no longer uses Apache HttpClient. Nonetheless SolrJ still includes deprecated SolrClient implementations for that (which will be removed eventually), and many tests still use it. Also, there were server metrics relating to HTTP client connection pools that no longer exist. * solrj-streaming DriverImpl, URI query parsing\ * PKIAuthenticationPlugin: setHeader alternative for tests * CloudAuthStreamTest: fixed SOLR-14222 ! (how?) * add httpcomponents to test compile classpath for some modules * HttpClientBuilderFactory; remove Apache HttpClient method * Metrics: no more UPDATE.updateShardHandler.maxConnections etc.
1 parent 753098f commit d5aaf27

File tree

61 files changed

+199
-786
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

61 files changed

+199
-786
lines changed

solr/CHANGES.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,10 @@ Deprecation Removals
149149

150150
* SOLR-17742: Removed the handleSelect option of <requestDispatcher>. (Gaurav Tuli, David Smiley)
151151

152+
* SOLR-17872: Solr no longer uses Apache HttpClient. Nonetheless SolrJ still includes deprecated SolrClient implementations
153+
for that (which will be removed eventually), and many tests still use it. Also, there were server metrics
154+
relating to HTTP client connection pools that no longer exist. (David Smiley)
155+
152156
Dependency Upgrades
153157
---------------------
154158

solr/api/gradle.lockfile

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,9 +105,9 @@ org.apache.commons:commons-math3:3.6.1=jarValidation,testRuntimeClasspath
105105
org.apache.curator:curator-client:5.9.0=jarValidation,testCompileClasspath,testRuntimeClasspath
106106
org.apache.curator:curator-framework:5.9.0=jarValidation,testCompileClasspath,testRuntimeClasspath
107107
org.apache.curator:curator-test:5.9.0=jarValidation,testRuntimeClasspath
108-
org.apache.httpcomponents:httpclient:4.5.14=jarValidation,testCompileClasspath,testRuntimeClasspath
109-
org.apache.httpcomponents:httpcore:4.4.16=jarValidation,testCompileClasspath,testRuntimeClasspath
110-
org.apache.httpcomponents:httpmime:4.5.14=jarValidation,testCompileClasspath,testRuntimeClasspath
108+
org.apache.httpcomponents:httpclient:4.5.14=jarValidation,testRuntimeClasspath
109+
org.apache.httpcomponents:httpcore:4.4.16=jarValidation,testRuntimeClasspath
110+
org.apache.httpcomponents:httpmime:4.5.14=jarValidation,testRuntimeClasspath
111111
org.apache.logging.log4j:log4j-api:2.21.0=jarValidation,testRuntimeClasspath
112112
org.apache.logging.log4j:log4j-core:2.21.0=jarValidation,testRuntimeClasspath
113113
org.apache.logging.log4j:log4j-slf4j2-impl:2.21.0=jarValidation,testRuntimeClasspath

solr/benchmark/gradle.lockfile

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,9 @@ org.apache.commons:commons-math3:3.6.1=annotationProcessor,compileClasspath,jarV
7676
org.apache.curator:curator-client:5.9.0=compileClasspath,jarValidation,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
7777
org.apache.curator:curator-framework:5.9.0=compileClasspath,jarValidation,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
7878
org.apache.curator:curator-test:5.9.0=jarValidation,runtimeClasspath,testRuntimeClasspath
79-
org.apache.httpcomponents:httpclient:4.5.14=compileClasspath,jarValidation,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
80-
org.apache.httpcomponents:httpcore:4.4.16=compileClasspath,jarValidation,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
81-
org.apache.httpcomponents:httpmime:4.5.14=compileClasspath,jarValidation,runtimeClasspath,testCompileClasspath,testRuntimeClasspath
79+
org.apache.httpcomponents:httpclient:4.5.14=jarValidation,runtimeClasspath,testRuntimeClasspath
80+
org.apache.httpcomponents:httpcore:4.4.16=jarValidation,runtimeClasspath,testRuntimeClasspath
81+
org.apache.httpcomponents:httpmime:4.5.14=jarValidation,runtimeClasspath,testRuntimeClasspath
8282
org.apache.logging.log4j:log4j-api:2.21.0=jarValidation,runtimeClasspath,testRuntimeClasspath
8383
org.apache.logging.log4j:log4j-core:2.21.0=jarValidation,runtimeClasspath,testRuntimeClasspath
8484
org.apache.logging.log4j:log4j-slf4j2-impl:2.21.0=jarValidation,runtimeClasspath,testRuntimeClasspath

solr/core/build.gradle

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -117,9 +117,6 @@ dependencies {
117117
implementation libs.fasterxml.jackson.dataformat.smile
118118
implementation libs.fasterxml.jackson.dataformat.cbor
119119

120-
implementation libs.apache.httpcomponents.httpclient
121-
implementation libs.apache.httpcomponents.httpcore
122-
123120
implementation libs.eclipse.jetty.client
124121
implementation libs.eclipse.jetty.http
125122
implementation libs.eclipse.jetty.io
@@ -210,4 +207,6 @@ dependencies {
210207
testRuntimeOnly(libs.mockito.subclass, {
211208
exclude group: "net.bytebuddy", module: "byte-buddy-agent"
212209
})
210+
testImplementation libs.apache.httpcomponents.httpclient
211+
testImplementation libs.apache.httpcomponents.httpcore
213212
}

solr/core/gradle.lockfile

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -88,9 +88,9 @@ org.apache.commons:commons-math3:3.6.1=apiHelper,compileClasspath,jarValidation,
8888
org.apache.curator:curator-client:5.9.0=apiHelper,compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,testCompileClasspath,testRuntimeClasspath
8989
org.apache.curator:curator-framework:5.9.0=apiHelper,compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,testCompileClasspath,testRuntimeClasspath
9090
org.apache.curator:curator-test:5.9.0=jarValidation,testCompileClasspath,testRuntimeClasspath
91-
org.apache.httpcomponents:httpclient:4.5.14=apiHelper,compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,testCompileClasspath,testRuntimeClasspath
92-
org.apache.httpcomponents:httpcore:4.4.16=apiHelper,compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,testCompileClasspath,testRuntimeClasspath
93-
org.apache.httpcomponents:httpmime:4.5.14=apiHelper,compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,testCompileClasspath,testRuntimeClasspath
91+
org.apache.httpcomponents:httpclient:4.5.14=apiHelper,jarValidation,runtimeClasspath,runtimeLibs,testCompileClasspath,testRuntimeClasspath
92+
org.apache.httpcomponents:httpcore:4.4.16=apiHelper,jarValidation,runtimeClasspath,runtimeLibs,testCompileClasspath,testRuntimeClasspath
93+
org.apache.httpcomponents:httpmime:4.5.14=apiHelper,jarValidation,runtimeClasspath,runtimeLibs,testRuntimeClasspath
9494
org.apache.logging.log4j:log4j-api:2.21.0=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,testCompileClasspath,testRuntimeClasspath
9595
org.apache.logging.log4j:log4j-core:2.21.0=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,testCompileClasspath,testRuntimeClasspath
9696
org.apache.logging.log4j:log4j-slf4j2-impl:2.21.0=jarValidation,runtimeClasspath,runtimeLibs,testRuntimeClasspath

solr/core/src/java/org/apache/solr/core/CoreContainer.java

Lines changed: 0 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,6 @@
5555
import java.util.function.Function;
5656
import java.util.function.Supplier;
5757
import java.util.stream.Collectors;
58-
import org.apache.http.auth.AuthSchemeProvider;
59-
import org.apache.http.client.CredentialsProvider;
60-
import org.apache.http.config.Lookup;
6158
import org.apache.lucene.index.CorruptIndexException;
6259
import org.apache.lucene.search.IndexSearcher;
6360
import org.apache.lucene.store.Directory;
@@ -67,11 +64,6 @@
6764
import org.apache.solr.api.JerseyResource;
6865
import org.apache.solr.client.solrj.SolrRequest;
6966
import org.apache.solr.client.solrj.impl.Http2SolrClient;
70-
import org.apache.solr.client.solrj.impl.HttpClientUtil;
71-
import org.apache.solr.client.solrj.impl.SolrHttpClientBuilder;
72-
import org.apache.solr.client.solrj.impl.SolrHttpClientContextBuilder;
73-
import org.apache.solr.client.solrj.impl.SolrHttpClientContextBuilder.AuthSchemeRegistryProvider;
74-
import org.apache.solr.client.solrj.impl.SolrHttpClientContextBuilder.CredentialsProviderProvider;
7567
import org.apache.solr.client.solrj.io.SolrClientCache;
7668
import org.apache.solr.client.solrj.util.SolrIdentifierValidator;
7769
import org.apache.solr.cloud.CloudDescriptor;
@@ -148,7 +140,6 @@
148140
import org.apache.solr.security.AuditLoggerPlugin;
149141
import org.apache.solr.security.AuthenticationPlugin;
150142
import org.apache.solr.security.AuthorizationPlugin;
151-
import org.apache.solr.security.HttpClientBuilderPlugin;
152143
import org.apache.solr.security.PKIAuthenticationPlugin;
153144
import org.apache.solr.security.PublicKeyHandler;
154145
import org.apache.solr.security.SecurityPluginHolder;
@@ -594,58 +585,10 @@ private synchronized void initializeAuthenticationPlugin(
594585
}
595586

596587
private void setupHttpClientForAuthPlugin(Object authcPlugin) {
597-
if (authcPlugin instanceof HttpClientBuilderPlugin builderPlugin) {
598-
// Setup HttpClient for internode communication
599-
SolrHttpClientBuilder builder =
600-
builderPlugin.getHttpClientBuilder(HttpClientUtil.getHttpClientBuilder());
601-
602-
// The Hadoop Auth Plugin was removed in SOLR-17540, however leaving the below reference
603-
// for future readers, as there may be an option to simplify this logic.
604-
//
605-
// this caused plugins like KerberosPlugin to register its intercepts, but this intercept
606-
// logic is also handled by the pki authentication code when it decides to let the plugin
607-
// handle auth via its intercept - so you would end up with two intercepts
608-
// -->
609-
// shardHandlerFactory.setSecurityBuilder(builderPlugin); // calls setup for the authcPlugin
610-
// updateShardHandler.setSecurityBuilder(builderPlugin);
611-
// <--
612-
613-
// This should not happen here at all - it's only currently required due to its effect on
614-
// http1 clients in a test or two incorrectly counting on it for their configuration.
615-
// -->
616-
617-
SolrHttpClientContextBuilder httpClientBuilder = new SolrHttpClientContextBuilder();
618-
if (builder.getCredentialsProviderProvider() != null) {
619-
httpClientBuilder.setDefaultCredentialsProvider(
620-
new CredentialsProviderProvider() {
621-
622-
@Override
623-
public CredentialsProvider getCredentialsProvider() {
624-
return builder.getCredentialsProviderProvider().getCredentialsProvider();
625-
}
626-
});
627-
}
628-
if (builder.getAuthSchemeRegistryProvider() != null) {
629-
httpClientBuilder.setAuthSchemeRegistryProvider(
630-
new AuthSchemeRegistryProvider() {
631-
632-
@Override
633-
public Lookup<AuthSchemeProvider> getAuthSchemeRegistry() {
634-
return builder.getAuthSchemeRegistryProvider().getAuthSchemeRegistry();
635-
}
636-
});
637-
}
638-
639-
HttpClientUtil.setHttpClientRequestContextBuilder(httpClientBuilder);
640-
641-
// <--
642-
}
643-
644588
// Always register PKI auth interceptor, which will then delegate the decision of who should
645589
// secure each request to the configured authentication plugin.
646590
if (pkiAuthenticationSecurityBuilder != null
647591
&& !pkiAuthenticationSecurityBuilder.isInterceptorRegistered()) {
648-
pkiAuthenticationSecurityBuilder.getHttpClientBuilder(HttpClientUtil.getHttpClientBuilder());
649592
shardHandlerFactory.setSecurityBuilder(pkiAuthenticationSecurityBuilder);
650593
updateShardHandler.setSecurityBuilder(pkiAuthenticationSecurityBuilder);
651594
solrClientProvider.setSecurityBuilder(pkiAuthenticationSecurityBuilder);

solr/core/src/java/org/apache/solr/metrics/prometheus/node/SolrNodeHandlerMetric.java

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
package org.apache.solr.metrics.prometheus.node;
1818

1919
import com.codahale.metrics.Counter;
20-
import com.codahale.metrics.Gauge;
2120
import com.codahale.metrics.Meter;
2221
import com.codahale.metrics.Metric;
2322
import org.apache.solr.metrics.prometheus.SolrMetric;
@@ -27,7 +26,6 @@
2726
public class SolrNodeHandlerMetric extends SolrNodeMetric {
2827
public static final String NODE_REQUESTS = "solr_metrics_node_requests";
2928
public static final String NODE_SECONDS_TOTAL = "solr_metrics_node_requests_time";
30-
public static final String NODE_CONNECTIONS = "solr_metrics_node_connections";
3129

3230
public SolrNodeHandlerMetric(Metric dropwizardMetric, String metricName) {
3331
super(dropwizardMetric, metricName);
@@ -36,7 +34,6 @@ public SolrNodeHandlerMetric(Metric dropwizardMetric, String metricName) {
3634
/*
3735
* Metric examples being exported
3836
* ADMIN./admin/collections.requests
39-
* UPDATE.updateShardHandler.maxConnections
4037
*/
4138

4239
@Override
@@ -53,8 +50,6 @@ public void toPrometheus(SolrPrometheusFormatter formatter) {
5350
if (metricName.endsWith(".totalTime")) {
5451
labels.remove("type");
5552
formatter.exportCounter(NODE_SECONDS_TOTAL, (Counter) dropwizardMetric, getLabels());
56-
} else if (metricName.endsWith("Connections")) {
57-
formatter.exportGauge(NODE_CONNECTIONS, (Gauge<?>) dropwizardMetric, getLabels());
5853
} else if (dropwizardMetric instanceof Meter) {
5954
formatter.exportMeter(NODE_REQUESTS, (Meter) dropwizardMetric, getLabels());
6055
} else if (dropwizardMetric instanceof Counter) {

solr/core/src/java/org/apache/solr/security/AuthenticationPlugin.java

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,6 @@
2727
import java.util.Map;
2828
import java.util.Set;
2929
import java.util.concurrent.ConcurrentHashMap;
30-
import org.apache.http.HttpRequest;
31-
import org.apache.http.protocol.HttpContext;
3230
import org.apache.solr.core.SolrInfoBean;
3331
import org.apache.solr.metrics.SolrMetricsContext;
3432
import org.eclipse.jetty.client.Request;
@@ -117,25 +115,6 @@ public String getRemoteUser() {
117115
};
118116
}
119117

120-
/**
121-
* Override this method to intercept internode requests. This allows your authentication plugin to
122-
* decide on per-request basis whether it should handle inter-node requests or delegate to {@link
123-
* PKIAuthenticationPlugin}. Return true to indicate that your plugin did handle the request, or
124-
* false to signal that PKI plugin should handle it. This method will be called by {@link
125-
* PKIAuthenticationPlugin}'s interceptor.
126-
*
127-
* <p>If not overridden, this method will return true for plugins implementing {@link
128-
* HttpClientBuilderPlugin}. This method can be overridden by subclasses e.g. to set HTTP headers,
129-
* even if you don't use a clientBuilder.
130-
*
131-
* @param httpRequest the httpRequest that is about to be sent to another internal Solr node
132-
* @param httpContext the context of that request.
133-
* @return true if this plugin handled authentication for the request, else false
134-
*/
135-
protected boolean interceptInternodeRequest(HttpRequest httpRequest, HttpContext httpContext) {
136-
return this instanceof HttpClientBuilderPlugin;
137-
}
138-
139118
/**
140119
* Override this method to intercept internode requests. This allows your authentication plugin to
141120
* decide on per-request basis whether it should handle inter-node requests or delegate to {@link

solr/core/src/java/org/apache/solr/security/AuthorizationUtils.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,9 @@
3030
import java.util.ArrayList;
3131
import java.util.List;
3232
import java.util.Map;
33-
import org.apache.http.HttpStatus;
3433
import org.apache.solr.common.params.SolrParams;
3534
import org.apache.solr.core.CoreContainer;
35+
import org.eclipse.jetty.http.HttpStatus;
3636
import org.slf4j.Logger;
3737
import org.slf4j.LoggerFactory;
3838

@@ -113,7 +113,7 @@ public static AuthorizationFailure authorize(
113113
return new AuthorizationFailure(
114114
statusCode, "Unauthorized request, Response code: " + statusCode);
115115
}
116-
if (!(statusCode == HttpStatus.SC_ACCEPTED) && !(statusCode == HttpStatus.SC_OK)) {
116+
if (!(statusCode == HttpStatus.ACCEPTED_202) && !(statusCode == HttpStatus.OK_200)) {
117117
log.warn(
118118
"ERROR {} during authentication: {}", statusCode, authResponse.getMessage()); // nowarn
119119
if (shouldAudit(cores, AuditEvent.EventType.ERROR)) {

solr/core/src/java/org/apache/solr/security/BasicAuthPlugin.java

Lines changed: 12 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -33,29 +33,23 @@
3333
import java.util.Set;
3434
import java.util.StringTokenizer;
3535
import javax.security.auth.Subject;
36-
import org.apache.http.Header;
37-
import org.apache.http.HttpHeaders;
38-
import org.apache.http.HttpRequest;
39-
import org.apache.http.annotation.Contract;
40-
import org.apache.http.annotation.ThreadingBehavior;
41-
import org.apache.http.client.protocol.HttpClientContext;
42-
import org.apache.http.message.BasicHeader;
43-
import org.apache.http.protocol.HttpContext;
4436
import org.apache.solr.client.solrj.impl.Http2SolrClient;
4537
import org.apache.solr.common.SolrException;
4638
import org.apache.solr.common.SolrException.ErrorCode;
4739
import org.apache.solr.common.SpecProvider;
4840
import org.apache.solr.common.util.CommandOperation;
4941
import org.apache.solr.common.util.ValidatingJsonMap;
5042
import org.eclipse.jetty.client.Request;
43+
import org.eclipse.jetty.http.HttpField;
44+
import org.eclipse.jetty.http.HttpHeader;
5145
import org.slf4j.Logger;
5246
import org.slf4j.LoggerFactory;
5347

5448
public class BasicAuthPlugin extends AuthenticationPlugin
5549
implements ConfigEditablePlugin, SpecProvider {
5650
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
5751
private AuthenticationProvider authenticationProvider;
58-
private static final ThreadLocal<Header> authHeader = new ThreadLocal<>();
52+
private static final ThreadLocal<HttpField> authHeader = new ThreadLocal<>();
5953
private static final String X_REQUESTED_WITH_HEADER = "X-Requested-With";
6054
private boolean blockUnknown = true;
6155
private boolean forwardCredentials = false;
@@ -128,7 +122,7 @@ public boolean doAuthenticate(
128122
boolean isAjaxRequest = isAjaxRequest(request);
129123

130124
if (authHeader != null) {
131-
BasicAuthPlugin.authHeader.set(new BasicHeader("Authorization", authHeader));
125+
BasicAuthPlugin.authHeader.set(new HttpField("Authorization", authHeader));
132126
StringTokenizer st = new StringTokenizer(authHeader);
133127
if (st.hasMoreTokens()) {
134128
String basic = st.nextToken();
@@ -192,13 +186,14 @@ public boolean doAuthenticate(
192186
*/
193187
private Map<String, String> getPromptHeaders(boolean isAjaxRequest) {
194188
Map<String, String> headers = new HashMap<>(authenticationProvider.getPromptHeaders());
189+
String WWW_AUTH = HttpHeader.WWW_AUTHENTICATE.asString();
195190
if (isAjaxRequest
196-
&& headers.containsKey(HttpHeaders.WWW_AUTHENTICATE)
197-
&& headers.get(HttpHeaders.WWW_AUTHENTICATE).startsWith("Basic ")) {
198-
headers.put(HttpHeaders.WWW_AUTHENTICATE, "x" + headers.get(HttpHeaders.WWW_AUTHENTICATE));
191+
&& headers.containsKey(WWW_AUTH)
192+
&& headers.get(WWW_AUTH).startsWith("Basic ")) {
193+
headers.put(WWW_AUTH, "x" + headers.get(WWW_AUTH));
199194
log.debug(
200195
"Prefixing {} header for Basic Auth with 'x' to prevent browser basic auth popup",
201-
HttpHeaders.WWW_AUTHENTICATE);
196+
WWW_AUTH);
202197
}
203198
return headers;
204199
}
@@ -219,24 +214,6 @@ public interface AuthenticationProvider extends SpecProvider {
219214
Map<String, String> getPromptHeaders();
220215
}
221216

222-
@Override
223-
protected boolean interceptInternodeRequest(HttpRequest httpRequest, HttpContext httpContext) {
224-
if (forwardCredentials) {
225-
if (httpContext instanceof HttpClientContext httpClientContext) {
226-
if (httpClientContext.getUserToken() instanceof BasicAuthUserPrincipal principal) {
227-
String userPassBase64 =
228-
Base64.getEncoder()
229-
.encodeToString(
230-
(principal.getName() + ":" + principal.getPassword())
231-
.getBytes(StandardCharsets.UTF_8));
232-
httpRequest.setHeader(HttpHeaders.AUTHORIZATION, "Basic " + userPassBase64);
233-
return true;
234-
}
235-
}
236-
}
237-
return false;
238-
}
239-
240217
@Override
241218
protected boolean interceptInternodeRequest(Request request) {
242219
if (forwardCredentials) {
@@ -248,7 +225,8 @@ protected boolean interceptInternodeRequest(Request request) {
248225
(principal.getName() + ":" + principal.getPassword())
249226
.getBytes(StandardCharsets.UTF_8));
250227
request.headers(
251-
httpFields -> httpFields.add(HttpHeaders.AUTHORIZATION, "Basic " + userPassBase64));
228+
httpFields ->
229+
httpFields.add(HttpHeader.AUTHORIZATION.asString(), "Basic " + userPassBase64));
252230
return true;
253231
}
254232
}
@@ -280,7 +258,7 @@ static boolean isAjaxRequest(HttpServletRequest request) {
280258
return "XMLHttpRequest".equalsIgnoreCase(request.getHeader(X_REQUESTED_WITH_HEADER));
281259
}
282260

283-
@Contract(threading = ThreadingBehavior.IMMUTABLE)
261+
// IMMUTABLE
284262
private static class BasicAuthUserPrincipal implements Principal, Serializable {
285263
private String username;
286264
private final String password;

0 commit comments

Comments
 (0)