Hi all,

I'd like to propose making Solr's internal HTTP client pluggable so that
deployments which don't need Jetty can run without exercising the Jetty
HTTP client at all — in particular the embedded (EmbeddedSolrServer /
in-process CoreContainer) use case.

Motivation
----------
Jetty has a steady stream of CVEs reported against it. For deployments that
embed Solr and never serve HTTP through Jetty, keeping the Jetty HTTP
client on the hot path is pure liability: we inherit the CVE exposure and
the recurring maintenance cost of chasing Jetty version bumps for a
component we don't actually use at runtime. Being able to run the internal
client on the JDK HttpClient instead would remove that burden for embedded
users.

Current state
-------------
The pieces to do this cleanly are mostly already in place:

  - HttpJdkSolrClient and HttpJettySolrClient both extend the common
HttpSolrClientBase, so most consumers can work against the base type.
  - CloudSolrClient.Builder.withHttpClient(...) and SolrClientCache already
accept HttpSolrClientBase.

What is still hard-wired to Jetty on the internal path:

  - HttpSolrClientProvider hardcodes `new HttpJettySolrClient.Builder()`
and returns the concrete HttpJettySolrClient.
  - CoreContainer.getDefaultHttpSolrClient() returns HttpJettySolrClient.
  - HttpSolrCall's request-proxy path calls
getSolrClient().getHttpClient(), which is Jetty-only (returns
org.eclipse.jetty.client.HttpClient).
  - HttpClientBuilderPlugin.setup(HttpJettySolrClient) is Jetty-typed
(security plugins).
  - InstrumentedHttpListenerFactory implements the Jetty-only
HttpListenerFactory for update-path metrics/tracing.
  - SolrClientCache still casts to HttpJettySolrClient (there's already a
`// TODO support JDK` there).

Proposal
----------------------
Decouple the runtime path (not full classpath removal):

  1. Make HttpSolrClientProvider select the client implementation (Jetty vs
JDK) rather than hardcoding Jetty, and expose it as HttpSolrClientBase.
  2. Widen CoreContainer.getDefaultHttpSolrClient() to HttpSolrClientBase
and fix up the handful of callers.
  3. Handle the Jetty-only call sites gracefully when the JDK client is
selected:
       - the HttpSolrCall proxy path (getHttpClient()),
       - HttpClientBuilderPlugin.setup(...) (add a base-typed overload),
       - the InstrumentedHttpListenerFactory metrics/tracing hook,
       - the SolrClientCache cast (the existing TODO).

This keeps solrj-jetty on the classpath but ensures the Jetty client and
other Jetty dependancies are never instantiated on the selected path — so
embedded users can drop the Jetty jars from their runtime.


Open questions for the list
---------------------------
  - Selection mechanism: a system property (e.g. an internal-client-impl
setting) vs. a first-class flag on NodeConfig set by the embedded entry
points? I lean toward a system property for the first cut.
  - The proxy path and the update-path metrics listener are the two
features that genuinely differ under the JDK client. For embedded
single-node use both are typically irrelevant — is degrading them (rather
than reimplementing on JDK) acceptable as a first step?


If this direction sounds reasonable, I'm happy to open a JIRA and put up a
PR. Feedback very welcome, especially on the selection mechanism and on the
proxy/metrics trade-offs.

Thanks,
Chamila

Reply via email to