You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tika.apache.org by "nddipiazza (via GitHub)" <gi...@apache.org> on 2026/03/04 16:30:57 UTC
[PR] TIKA-4679: Add HTTP/2 support to tika-server via Jetty http2-server [tika]
nddipiazza opened a new pull request, #2672:
URL: https://github.com/apache/tika/pull/2672
## Summary
Adds HTTP/2 (h2c cleartext) support to tika-server by including the `org.eclipse.jetty.http2:http2-server` jar on the classpath. When this jar is present, CXF's Jetty transport automatically negotiates HTTP/2 alongside HTTP/1.1 on the existing port (default 9998). Existing HTTP/1.1 clients are completely unaffected.
This implements [TIKA-4679](https://issues.apache.org/jira/browse/TIKA-4679). The core dependency change was originally contributed by Lawrence Moorehead ([@elemdisc](https://github.com/elemdisc)) — see [elemdisc/tika PR#1](https://github.com/elemdisc/tika/pull/1) — and is cherry-picked here with full author credit.
---
## Changes
### tika-parent/pom.xml
- Added `http2-server` to the dependency management block alongside the existing `http2-hpack`, `http2-client`, `http2-common` entries (all at `${jetty.http2.version}`)
### tika-server/tika-server-core/pom.xml _(Lawrence Moorehead's commit)_
- Added `org.eclipse.jetty.http2:http2-server` runtime dependency (version from parent BOM)
### tika-server/tika-server-core/src/test/.../TikaServerIntegrationTest.java _(Lawrence Moorehead's commit)_
- Added `testH2c()` unit test that sends a request via `HttpClient.Version.HTTP_2` and asserts the response was served over HTTP/2
### tika-e2e-tests/tika-server/ _(new module)_
- New e2e module that starts the actual fat-jar process and validates HTTP/2 (h2c) end-to-end
- Tests are skipped by default; run with `-Pe2e`
- Wired into `tika-e2e-tests/pom.xml`
---
## How it works
Adding `http2-server` to the classpath is sufficient for h2c (HTTP/2 cleartext) support. CXF's `JettyHTTPServerEngineFactory` detects the jar at startup and wires in `HTTP2CServerConnectionFactory`. No startup code changes are required.
For h2 over TLS (recommended for production), configure `TlsConfig` in `tika-server.json`. Java 17's built-in ALPN handles protocol negotiation automatically — no separate ALPN agent is needed.
---
## Port management
- Single port (9998 by default) continues to serve both HTTP/1.1 and HTTP/2
- No second port added; Docker `EXPOSE 9998` and health-check are unchanged
- The fat-jar grows by ~500 KB from the new jar
---
## Shutdown note
HTTP/2 multiplexes multiple requests over a single TCP connection. The current `shutdownNow()` path does not send a GOAWAY frame before closing. Under moderate load this is acceptable for h2c, but a future improvement could add a drain timeout for graceful HTTP/2 shutdown.
---
## Backward compatibility
Purely additive classpath change:
- Does **not** change the default port
- Does **not** require TLS (TLS remains opt-in)
- Does **not** break any existing HTTP/1.1 client
- Does **not** change the REST API surface
---
## Testing Instructions
```bash
# Unit test (no external process)
mvn test -pl tika-server/tika-server-core -Dtest=TikaServerIntegrationTest#testH2c
# E2E test (requires fat-jar to be built first)
mvn package -pl tika-server/tika-server-standard -DskipTests
mvn test -pl tika-e2e-tests/tika-server -Pe2e
```
Manually with curl (after starting the server):
```bash
# HTTP/2 cleartext (h2c)
curl --http2-prior-knowledge http://localhost:9998/tika
# HTTP/1.1 — unchanged behavior
curl http://localhost:9998/tika
```
---
## Review Checklist
- [ ] `http2-server` version comes from `${jetty.http2.version}` in parent BOM (not hardcoded)
- [ ] Existing HTTP/1.1 tests still pass
- [ ] `TikaServerIntegrationTest#testH2c` passes
- [ ] E2E module compiles and tests pass with `-Pe2e`
- [ ] No second port introduced
---
## Potential Concerns
- **h2c vs h2**: This PR enables h2c (cleartext). For h2 over TLS an additional `jetty-alpn-java-server` dependency may be needed depending on the Jetty version and JVM. This can be addressed in a follow-up.
- **Reverse proxies**: Most reverse proxies (nginx, AWS ALB, GCP LB) do not support h2c — they require h2 over TLS. For internal service-to-service use h2c is fine; for edge deployments, TLS is recommended.
- **Fat-jar size**: The `http2-server` jar adds ~500 KB to `tika-server-standard`. This also increases the `apache/tika` Docker image slightly.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: dev-unsubscribe@tika.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] TIKA-4679: Add HTTP/2 support to tika-server via Jetty http2-server [tika]
Posted by "Copilot (via GitHub)" <gi...@apache.org>.
Copilot commented on code in PR #2672:
URL: https://github.com/apache/tika/pull/2672#discussion_r2889591071
##########
tika-e2e-tests/tika-server/src/test/java/org/apache/tika/server/e2e/TikaServerHttp2Test.java:
##########
@@ -0,0 +1,200 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tika.server.e2e;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.net.ServerSocket;
+import java.net.URI;
+import java.net.http.HttpClient;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.time.Duration;
+import java.time.Instant;
+
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Assumptions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Tag;
+import org.junit.jupiter.api.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * End-to-end test verifying that tika-server-standard supports HTTP/2 (h2c cleartext).
+ *
+ * Starts the real fat-jar, sends a request using Java's HttpClient configured for HTTP/2,
+ * and asserts the response was served over HTTP/2. This validates the runtime classpath
+ * has the Jetty http2-server jar and CXF negotiates h2c correctly.
+ *
+ * Run with: mvn test -pl tika-e2e-tests/tika-server -Pe2e
+ *
+ * Inspired by Lawrence Moorehead's original contribution (elemdisc/tika PR#1, TIKA-4679).
+ */
+@Tag("E2ETest")
+public class TikaServerHttp2Test {
+
+ private static final Logger log = LoggerFactory.getLogger(TikaServerHttp2Test.class);
+ private static final long SERVER_STARTUP_TIMEOUT_MS = 90_000;
+ private static final String STATUS_PATH = "/status";
+
+ private Process serverProcess;
+ private int port;
+ private String endPoint;
+
+ @BeforeEach
+ void startServer() throws Exception {
+ port = findFreePort();
+ endPoint = "http://localhost:" + port;
+
+ String jarPath = System.getProperty("tika.server.jar");
+ if (jarPath == null) {
+ // fall back to conventional location relative to this module
+ Path moduleDir = Paths.get("").toAbsolutePath();
+ Path repoRoot = moduleDir;
+ while (repoRoot != null && !repoRoot.resolve("tika-server").toFile().isDirectory()) {
+ repoRoot = repoRoot.getParent();
+ }
+ if (repoRoot == null) {
+ throw new IllegalStateException("Cannot locate tika root. Pass -Dtika.server.jar=/path/to/tika-server-standard.jar");
+ }
+ jarPath = repoRoot.resolve("tika-server/tika-server-standard/target")
+ .toAbsolutePath()
+ .toString() + "/tika-server-standard-" +
+ System.getProperty("tika.version", "4.0.0-SNAPSHOT") + ".jar";
+ }
+
+ Path jar = Paths.get(jarPath);
+ Assumptions.assumeTrue(Files.exists(jar),
+ "Fat-jar not found at " + jarPath + "; skipping HTTP/2 e2e test. " +
+ "Build with: mvn package -pl tika-server/tika-server-standard -DskipTests");
+
+ log.info("Starting tika-server-standard from: {}", jarPath);
+ ProcessBuilder pb = new ProcessBuilder(
+ "java", "-jar", jarPath,
+ "-p", String.valueOf(port),
+ "-h", "localhost"
+ );
+ pb.redirectErrorStream(true);
+ serverProcess = pb.start();
+
+ // Drain output in background so the process doesn't block
+ Thread drainThread = new Thread(() -> {
+ try (BufferedReader reader = new BufferedReader(
+ new InputStreamReader(serverProcess.getInputStream(), UTF_8))) {
+ String line;
+ while ((line = reader.readLine()) != null) {
+ log.debug("tika-server: {}", line);
+ }
+ } catch (Exception e) {
+ log.debug("Server output stream closed", e);
+ }
+ });
+ drainThread.setDaemon(true);
+ drainThread.start();
+
+ awaitServerStartup();
+ }
+
Review Comment:
The `stopServer()` method calls `serverProcess.waitFor()` without a timeout. If the server process doesn't terminate after `destroy()` (SIGTERM), this will block the test indefinitely. The existing `IntegrationTestBase.tearDown()` uses a safer pattern: `waitFor(5, TimeUnit.SECONDS)` followed by `destroyForcibly()` and then `waitFor(30, TimeUnit.SECONDS)`. Consider adopting the same approach here to prevent hanging CI builds.
##########
tika-e2e-tests/tika-server/src/test/java/org/apache/tika/server/e2e/TikaServerHttp2Test.java:
##########
@@ -0,0 +1,200 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tika.server.e2e;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.net.ServerSocket;
+import java.net.URI;
+import java.net.http.HttpClient;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.time.Duration;
+import java.time.Instant;
+
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Assumptions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Tag;
+import org.junit.jupiter.api.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * End-to-end test verifying that tika-server-standard supports HTTP/2 (h2c cleartext).
+ *
+ * Starts the real fat-jar, sends a request using Java's HttpClient configured for HTTP/2,
+ * and asserts the response was served over HTTP/2. This validates the runtime classpath
+ * has the Jetty http2-server jar and CXF negotiates h2c correctly.
+ *
+ * Run with: mvn test -pl tika-e2e-tests/tika-server -Pe2e
+ *
+ * Inspired by Lawrence Moorehead's original contribution (elemdisc/tika PR#1, TIKA-4679).
+ */
+@Tag("E2ETest")
+public class TikaServerHttp2Test {
+
+ private static final Logger log = LoggerFactory.getLogger(TikaServerHttp2Test.class);
+ private static final long SERVER_STARTUP_TIMEOUT_MS = 90_000;
+ private static final String STATUS_PATH = "/status";
+
+ private Process serverProcess;
+ private int port;
+ private String endPoint;
+
+ @BeforeEach
+ void startServer() throws Exception {
+ port = findFreePort();
+ endPoint = "http://localhost:" + port;
+
+ String jarPath = System.getProperty("tika.server.jar");
+ if (jarPath == null) {
+ // fall back to conventional location relative to this module
+ Path moduleDir = Paths.get("").toAbsolutePath();
+ Path repoRoot = moduleDir;
Review Comment:
The variable `moduleDir` is assigned on line 71 but never used — `repoRoot` is immediately initialized to the same value on line 72. You can remove `moduleDir` and initialize `repoRoot` directly: `Path repoRoot = Paths.get("").toAbsolutePath();`.
```suggestion
Path repoRoot = Paths.get("").toAbsolutePath();
```
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: dev-unsubscribe@tika.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] TIKA-4679: Add HTTP/2 support to tika-server via Jetty http2-server [tika]
Posted by "tballison (via GitHub)" <gi...@apache.org>.
tballison commented on PR #2672:
URL: https://github.com/apache/tika/pull/2672#issuecomment-4114721736
+1
I don't like adding this without more motivation, but I couldn't find any way that it causes security problems. ¯\_(ツ)_/¯
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: dev-unsubscribe@tika.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] TIKA-4679: Add HTTP/2 support to tika-server via Jetty http2-server [tika]
Posted by "nddipiazza (via GitHub)" <gi...@apache.org>.
nddipiazza commented on PR #2672:
URL: https://github.com/apache/tika/pull/2672#issuecomment-4117940416
@tballison from community member who created jira: "The main motivation is that Google Cloud Run limits request sizes to 32 mb on HTTP1.1, but has no hard cap with HTTP2. (Containers inside Google Cloud Run run without HTTPS.)"
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: dev-unsubscribe@tika.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] TIKA-4679: Add HTTP/2 support to tika-server via Jetty http2-server [tika]
Posted by "nddipiazza (via GitHub)" <gi...@apache.org>.
nddipiazza commented on PR #2672:
URL: https://github.com/apache/tika/pull/2672#issuecomment-4005601982
Addressed both Copilot review comments in commit 30b9ff303:
1. **Unused `moduleDir` variable** — removed; `repoRoot` is now initialized directly from `Paths.get("").toAbsolutePath()`
2. **`stopServer()` blocking on `waitFor()`** — adopted the safer pattern from `IntegrationTestBase.tearDown()`: `waitFor(5s)` → `destroyForcibly()` → `waitFor(30s)` to prevent CI hangs
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: dev-unsubscribe@tika.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] TIKA-4679: Add HTTP/2 support to tika-server via Jetty http2-server [tika]
Posted by "nddipiazza (via GitHub)" <gi...@apache.org>.
nddipiazza commented on PR #2672:
URL: https://github.com/apache/tika/pull/2672#issuecomment-4042056109
@copilot should i be trying to make the http2 option optional so people aren't forced to have that on classpath?
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: dev-unsubscribe@tika.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] TIKA-4679: Add HTTP/2 support to tika-server via Jetty http2-server [tika]
Posted by "nddipiazza (via GitHub)" <gi...@apache.org>.
nddipiazza merged PR #2672:
URL: https://github.com/apache/tika/pull/2672
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: dev-unsubscribe@tika.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] TIKA-4679: Add HTTP/2 support to tika-server via Jetty http2-server [tika]
Posted by "tballison (via GitHub)" <gi...@apache.org>.
tballison commented on PR #2672:
URL: https://github.com/apache/tika/pull/2672#issuecomment-4120625556
LOL, y, I guess?
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: dev-unsubscribe@tika.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] TIKA-4679: Add HTTP/2 support to tika-server via Jetty http2-server [tika]
Posted by "tballison (via GitHub)" <gi...@apache.org>.
tballison commented on PR #2672:
URL: https://github.com/apache/tika/pull/2672#issuecomment-3999953963
>. For h2 over TLS an additional jetty-alpn-java-server dependency may be needed depending on the Jetty version and JVM. This can be addressed in a follow-up.
I think we're good with Java 17.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: dev-unsubscribe@tika.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
Re: [PR] TIKA-4679: Add HTTP/2 support to tika-server via Jetty http2-server [tika]
Posted by "nddipiazza (via GitHub)" <gi...@apache.org>.
nddipiazza commented on PR #2672:
URL: https://github.com/apache/tika/pull/2672#issuecomment-4104395785
@tballison mind me merging this?
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: dev-unsubscribe@tika.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org