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
