This is an automated email from the ASF dual-hosted git repository.

tballison pushed a commit to branch TIKA-4809-stage-4
in repository https://gitbox.apache.org/repos/asf/tika.git

commit 1719f8207d7864df628350c137e2ff8ab39df461
Author: tallison <[email protected]>
AuthorDate: Sun Aug 9 20:46:06 2026 -0400

    TIKA-4809: Remove meta_* injection and the dead X-Tika-Handler constant
---
 .../migration-to-4x/migrating-tika-server-4x.adoc  | 69 ++++++++++++++++++++++
 .../pages/migration-to-4x/migrating-to-4x.adoc     |  2 +-
 docs/modules/ROOT/pages/pipes/cpu-sizing.adoc      |  2 +-
 .../ROOT/pages/using-tika/server/index.adoc        | 11 ----
 .../tika/server/core/resource/TikaResource.java    | 28 +++------
 .../standard/RecursiveMetadataResourceTest.java    | 20 -------
 6 files changed, 80 insertions(+), 52 deletions(-)

diff --git 
a/docs/modules/ROOT/pages/migration-to-4x/migrating-tika-server-4x.adoc 
b/docs/modules/ROOT/pages/migration-to-4x/migrating-tika-server-4x.adoc
index fad6b193e4..51868461e2 100644
--- a/docs/modules/ROOT/pages/migration-to-4x/migrating-tika-server-4x.adoc
+++ b/docs/modules/ROOT/pages/migration-to-4x/migrating-tika-server-4x.adoc
@@ -151,6 +151,75 @@ The following `TikaServerConfig` options have been removed:
 * `taskPulseMillis` - No longer needed
 * `minimumTimeoutMillis` - No longer needed
 
+=== Configuration via HTTP Headers Removed
+
+4.x configures parsing through the tika-config file, not through request 
headers.
+The remaining per-request configuration headers have been removed and are now
+**silently ignored** if sent — the request succeeds, the header has no effect:
+
+|===
+|Removed header |Replacement
+
+|`writeLimit`
+|`parse-context.output-limits.writeLimit`
+
+|`throwOnWriteLimitReached`
+|`parse-context.output-limits.throwOnWriteLimit`
+
+|`maxEmbeddedResources`, `maxEmbeddedCount`
+|`parse-context.embedded-limits.maxCount`
+
+|`meta_*` (arbitrary metadata injection)
+|_no replacement_ — see below
+
+|`X-Tika-Handler`
+|Use an explicit handler path (`/tika/text`, `/rmeta/xml`, `/tika/json/html`, 
...)
+|===
+
+The `X-Tika-OCR*` and `X-Tika-PDF*` header families were removed earlier in the
+4.x line. Parser configuration is now supplied as JSON.
+
+[source,json]
+----
+{
+  "parse-context": {
+    "output-limits": {
+      "writeLimit": 100000,
+      "throwOnWriteLimit": false
+    },
+    "embedded-limits": {
+      "maxCount": 10
+    }
+  }
+}
+----
+
+**Migration:** move these settings into your tika-config. For per-request 
values,
+POST to a `/config` endpoint (`/tika/config`, `/tika/config/json`, 
`/rmeta/config`,
+`/meta/config`) with the JSON above as the multipart `config` part; this 
requires
+`allowPerRequestConfig=true`.
+
+[IMPORTANT]
+====
+Two capabilities are genuinely gone, not relocated.
+
+**Per-request output bounds without `allowPerRequestConfig`.** With the headers
+removed and per-request config off by default, a caller can no longer bound the
+output of a single request; the limits are whatever the operator configured. If
+you relied on clients setting their own `writeLimit`, either enable
+`allowPerRequestConfig` or set a server-wide limit.
+
+**Client-supplied metadata (`meta_*`).** Headers prefixed `meta_` were copied
+into the returned metadata under the remainder of the header name, with no key
+restrictions — so a request could also overwrite keys Tika itself populates.
+There is no replacement on the push endpoints; attach provenance on your side 
of
+the call, or use `/pipes`, where the `FetchEmitTuple` carries metadata.
+====
+
+Transport headers are unaffected: `Content-Disposition`/`File-Name`,
+`Content-Type` and `Content-Length` still describe the payload and still
+influence detection.
+
 === Removed Features
 
 * **Fetcher-based streaming** - The `InputStreamFactory` pattern for fetching 
documents via HTTP headers (`fetcherName`, `fetchKey`) has been removed. All 
documents are now processed via temp files through the pipes infrastructure.
diff --git a/docs/modules/ROOT/pages/migration-to-4x/migrating-to-4x.adoc 
b/docs/modules/ROOT/pages/migration-to-4x/migrating-to-4x.adoc
index 8ce3c69afb..a4d178eb59 100644
--- a/docs/modules/ROOT/pages/migration-to-4x/migrating-to-4x.adoc
+++ b/docs/modules/ROOT/pages/migration-to-4x/migrating-to-4x.adoc
@@ -45,7 +45,7 @@ If you have build scripts or container images that drop in 
just the jar, update
 In 3.x the default content handler produced XHTML/XML. In 4.x the default is 
**Markdown** everywhere:
 
 * `tika-app` outputs Markdown by default (was XHTML). Pass `-x`/`--xml`, 
`-h`/`--html`, or `-t`/`--text` to choose another format.
-* `tika-server` — the `/tika` and `/rmeta` endpoints return Markdown content 
by default (was XHTML/XML). Use an explicit handler path (`/tika/xml`, 
`/rmeta/xml`, ...) or the `X-Tika-Handler` header to choose another format.
+* `tika-server` — the `/tika` and `/rmeta` endpoints return Markdown content 
by default (was XHTML/XML). Use an explicit handler path (`/tika/xml`, 
`/rmeta/xml`, ...) to choose another format.
 * The async/pipes CLI emits Markdown by default (was plain text). Use 
`--handler x` (etc.) to choose another format.
 
 If you parse the extracted content programmatically and expect XHTML/XML, 
request it explicitly as shown above (TIKA-4663).
diff --git a/docs/modules/ROOT/pages/pipes/cpu-sizing.adoc 
b/docs/modules/ROOT/pages/pipes/cpu-sizing.adoc
index 831ed445d0..a076f9ac99 100644
--- a/docs/modules/ROOT/pages/pipes/cpu-sizing.adoc
+++ b/docs/modules/ROOT/pages/pipes/cpu-sizing.adoc
@@ -169,7 +169,7 @@ report `autoCap=user-set in forkedJvmArgs`.
 A reasonable starting point is **~2 GB of heap per forked worker** (passed via 
`-Xmx2g` in `forkedJvmArgs`). The number falls out of three independent 
constraints any of which can dominate:
 
 * **Worst-case PDF parsing.** A handful of pathological PDFs in any reasonably 
large corpus will allocate hundreds of MB of intermediate object data per 
document — large image streams, deeply nested form fields, big embedded fonts. 
Smaller heaps OOM on those documents; larger heaps just let GC clean up between 
docs.
-* **Embedded-document explosion.** A zip-bomb-shaped office document with 
thousands of embedded objects multiplies per-doc allocation by the embedding 
count. The `maxEmbeddedResources` setting caps the count, but each retained 
object still lives in the heap until the whole tree finishes parsing.
+* **Embedded-document explosion.** A zip-bomb-shaped office document with 
thousands of embedded objects multiplies per-doc allocation by the embedding 
count. The `parse-context.embedded-limits.maxCount` setting caps the count, but 
each retained object still lives in the heap until the whole tree finishes 
parsing.
 * **GC headroom.** G1GC behaves poorly above ~85% occupancy. A `-Xmx2g` worker 
comfortably handles documents that allocate up to ~1.5 GB of live data; below 
that you start trading throughput for memory.
 
 This is a default — not a tuning recommendation. To right-size for your 
specific corpus:
diff --git a/docs/modules/ROOT/pages/using-tika/server/index.adoc 
b/docs/modules/ROOT/pages/using-tika/server/index.adoc
index 113cdb6071..72de6d31a4 100644
--- a/docs/modules/ROOT/pages/using-tika/server/index.adoc
+++ b/docs/modules/ROOT/pages/using-tika/server/index.adoc
@@ -143,17 +143,6 @@ the JSON variant, you can also nest a handler — 
`/tika/json/text`,
 envelope; that nested handler accepts the full set (`text`, `html`, `xml`,
 `md`, `markdown`, `body`, `ignore`).
 
-==== `X-Tika-Handler` header
-
-For the root `/tika` PUT endpoint you can also pick the handler with a header:
-
-[source,bash]
-----
-curl -T document.pdf -H "X-Tika-Handler: markdown" http://localhost:9998/tika
-----
-
-Accepted values: `text`, `html`, `xml`, `markdown` (or `md`), `body`, 
`ignore`. The default is `markdown`.
-
 === Recursive Metadata (`/rmeta`)
 
 Returns metadata for the container document and all embedded documents as a 
JSON
diff --git 
a/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/resource/TikaResource.java
 
b/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/resource/TikaResource.java
index a6ed9acf7c..bf2f8582bd 100644
--- 
a/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/resource/TikaResource.java
+++ 
b/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/resource/TikaResource.java
@@ -76,12 +76,6 @@ import org.apache.tika.server.core.TikaServerParseException;
 public class TikaResource {
 
     public static final String GREETING = "This is Tika Server (" + 
Tika.getString() + "). Please PUT\n";
-    /**
-     * Header to specify the handler type for content extraction.
-     * Valid values: text, html, xml, markdown, ignore (default: text)
-     */
-    public static final String HANDLER_TYPE_HEADER = "X-Tika-Handler";
-    private static final String META_PREFIX = "meta_";
     private static final Logger LOG = 
LoggerFactory.getLogger(TikaResource.class);
 
     // Instance (not static): production only ever creates one CXF server -- 
and so
@@ -211,6 +205,15 @@ public class TikaResource {
             mediaType = null;
         }
 
+        // Transport content types, not statements about the document: curl 
sends
+        // x-www-form-urlencoded by default for --data-binary, and 
multipart/form-data
+        // describes the envelope rather than the file inside it.
+        if (mediaType != null
+                && 
(mediaType.equals(jakarta.ws.rs.core.MediaType.APPLICATION_FORM_URLENCODED_TYPE)
+                || 
mediaType.equals(jakarta.ws.rs.core.MediaType.MULTIPART_FORM_DATA_TYPE))) {
+            mediaType = null;
+        }
+
         if (mediaType != null) {
             metadata.set(Metadata.CONTENT_TYPE, mediaType.toString());
             metadata.add(TikaCoreProperties.CONTENT_TYPE_USER_OVERRIDE, 
mediaType.toString());
@@ -219,19 +222,6 @@ public class TikaResource {
         if (httpHeaders.containsKey("Content-Length")) {
             metadata.set(Metadata.CONTENT_LENGTH, 
httpHeaders.getFirst("Content-Length"));
         }
-
-        for (Map.Entry<String, List<String>> e : httpHeaders.entrySet()) {
-            if (e
-                    .getKey()
-                    .startsWith(META_PREFIX)) {
-                String tikaKey = e
-                        .getKey()
-                        .substring(META_PREFIX.length());
-                for (String value : e.getValue()) {
-                    metadata.add(tikaKey, value);
-                }
-            }
-        }
     }
 
     /**
diff --git 
a/tika-server/tika-server-standard/src/test/java/org/apache/tika/server/standard/RecursiveMetadataResourceTest.java
 
b/tika-server/tika-server-standard/src/test/java/org/apache/tika/server/standard/RecursiveMetadataResourceTest.java
index de3605813e..bd37132d93 100644
--- 
a/tika-server/tika-server-standard/src/test/java/org/apache/tika/server/standard/RecursiveMetadataResourceTest.java
+++ 
b/tika-server/tika-server-standard/src/test/java/org/apache/tika/server/standard/RecursiveMetadataResourceTest.java
@@ -30,8 +30,6 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 
-import jakarta.ws.rs.core.MultivaluedHashMap;
-import jakarta.ws.rs.core.MultivaluedMap;
 import jakarta.ws.rs.core.Response;
 import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream;
 import org.apache.cxf.jaxrs.JAXRSServerFactoryBean;
@@ -175,24 +173,6 @@ public class RecursiveMetadataResourceTest extends 
CXFTestBase {
                 .get("tk:digest:MD5"));
     }
 
-    @Test
-    public void testHeaders() throws Exception {
-        MultivaluedMap<String, String> map = new MultivaluedHashMap<>();
-        map.addAll("meta_mymeta", "first", "second", "third");
-
-        Response response = WebClient
-                .create(endPoint + META_PATH)
-                .headers(map)
-                .accept("application/json")
-                
.put(ClassLoader.getSystemResourceAsStream(TEST_RECURSIVE_DOC));
-
-        Reader reader = new InputStreamReader((InputStream) 
response.getEntity(), UTF_8);
-        List<Metadata> metadataList = JsonMetadataList.fromJson(reader);
-        assertEquals("first,second,third", metadataList
-                .get(0)
-                .get("mymeta"));
-    }
-
     @Test
     public void testPasswordProtected() throws Exception {
         // Test that encrypted document without password shows error

Reply via email to