How to Configure Jetty Server to Handle Long HTTP GET Query Strings for Solr Applications


12 views

When working with Solr via Jetty, you'll eventually hit the server's default limit for HTTP GET query string length (typically around 8KB). This becomes apparent when:

  • Complex Solr queries with multiple filters and facets
  • Large "fq" (filter query) parameters
  • Applications generating dynamic queries programmatically

The symptoms manifest as connection resets or truncated queries, particularly when using PHP libraries like Apache_Solr_Service that rely on GET requests.

Jetty enforces these limits through two key parameters:

org.eclipse.jetty.server.Request.maxFormContentSize
org.eclipse.jetty.server.Request.maxFormKeys

There are three approaches to address this:

1. Jetty XML Configuration

Edit your jetty.xml or jetty-http.xml:

<Configure id="Server" class="org.eclipse.jetty.server.Server">
  <Call name="setAttribute">
    <Arg>org.eclipse.jetty.server.Request.maxFormContentSize</Arg>
    <Arg>200000</Arg> <!-- 200KB -->
  </Call>
</Configure>

2. Java System Property Approach

Add this to your Jetty startup script:

java -Dorg.eclipse.jetty.server.Request.maxFormContentSize=200000 \
     -jar start.jar

3. Programmatic Configuration

If you're embedding Jetty:

Server server = new Server();
server.setAttribute("org.eclipse.jetty.server.Request.maxFormContentSize", 200000);

Verify the changes with a simple test:

import org.eclipse.jetty.server.Server;

public class ConfigTest {
  public static void main(String[] args) {
    Server server = new Server();
    System.out.println("Max form content size: " + 
      server.getAttribute("org.eclipse.jetty.server.Request.maxFormContentSize"));
  }
}

When increasing these limits:

  • Monitor memory usage - larger buffers require more heap
  • Consider request timeout settings (setIdleTimeout)
  • Review query optimization - very long queries may indicate inefficient filters

For PHP applications, consider using Solarium (a PHP Solr client) which properly handles POST requests:

$client = new Solarium\Client($config);
$query = $client->createSelect();
$query->setQuery('*:*');
// Add your complex filters here
$resultset = $client->select($query);

When working with Solr through Jetty, you might encounter connection resets during long GET requests. This happens because Jetty enforces a default maximum length for HTTP GET query strings (typically 8KB-16KB depending on version). For Solr applications with complex queries, this limit can become problematic.

The key configuration elements controlling this behavior are:

  • HttpConfiguration: Manages general HTTP protocol settings
  • HttpConnectionFactory: Handles the actual connection parameters
  • ServerConnector: The network interface implementation

Here's how to modify your Jetty configuration (typically in jetty.xml or your startup code):

// For Jetty 9.x/10.x
Server server = new Server();

HttpConfiguration httpConfig = new HttpConfiguration();
httpConfig.setRequestHeaderSize(65536);  // Header size
httpConfig.setResponseHeaderSize(65536); // Response headers
httpConfig.setHeaderCacheSize(32768);    // Header cache

// Set the form size (affects GET query strings)
httpConfig.setFormEncodedMethods("GET,POST");
httpConfig.setFormContentSize(262144);   // 256KB limit

ServerConnector connector = new ServerConnector(server,
    new HttpConnectionFactory(httpConfig));
connector.setPort(8080);
server.addConnector(connector);

If you're using embedded Jetty with Solr:

ContextHandlerCollection contexts = new ContextHandlerCollection();
WebAppContext webapp = new WebAppContext();
webapp.setContextPath("/solr");

HttpConfiguration httpConfig = new HttpConfiguration();
httpConfig.setFormContentSize(524288); // 512KB for large queries

ServerConnector connector = new ServerConnector(server,
    new HttpConnectionFactory(httpConfig));
connector.setHost("0.0.0.0");
connector.setPort(8983);

server.setConnectors(new Connector[] { connector });
server.setHandler(contexts);

For XML configuration (jetty.xml):

<Configure id="Server" class="org.eclipse.jetty.server.Server">
  <Call name="addConnector">
    <Arg>
      <New class="org.eclipse.jetty.server.ServerConnector">
        <Arg name="server"><Ref refid="Server" /></Arg>
        <Arg name="factories">
          <Array type="org.eclipse.jetty.server.ConnectionFactory">
            <Item>
              <New class="org.eclipse.jetty.server.HttpConnectionFactory">
                <Arg name="config">
                  <New class="org.eclipse.jetty.server.HttpConfiguration">
                    <Set name="formContentSize">1048576</Set> <!-- 1MB -->
                    <Set name="requestHeaderSize">65536</Set>
                  </New>
                </Arg>
              </New>
            </Item>
          </Array>
        </Arg>
        <Set name="port">8983</Set>
      </New>
    </Arg>
  </Call>
</Configure>
  • Verify the settings took effect by checking System.out.println(httpConfig.toString())
  • Monitor Jetty logs for any "Too large" warnings
  • Consider URI encoding efficiency - some characters expand when encoded
  • For extremely large queries, consider redesigning to use POST despite client limitations

Increasing the query string limit impacts:

  • Memory usage per connection
  • Potential denial-of-service vulnerability surface
  • Network buffer requirements

Benchmark your application after making these changes to ensure stability.