Skip to content

Commit 2a59ed2

Browse files
authored
TIKA-4809 stage 4
2 parents dbf709e + b3214b3 commit 2a59ed2

12 files changed

Lines changed: 138 additions & 475 deletions

File tree

docs/modules/ROOT/pages/migration-to-4x/migrating-tika-server-4x.adoc

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,75 @@ The following `TikaServerConfig` options have been removed:
176176
* `taskPulseMillis` - No longer needed
177177
* `minimumTimeoutMillis` - No longer needed
178178
179+
=== Configuration via HTTP Headers Removed
180+
181+
4.x configures parsing through the tika-config file, not through request headers.
182+
The remaining per-request configuration headers have been removed and are now
183+
**silently ignored** if sent — the request succeeds, the header has no effect:
184+
185+
|===
186+
|Removed header |Replacement
187+
188+
|`writeLimit`
189+
|`parse-context.output-limits.writeLimit`
190+
191+
|`throwOnWriteLimitReached`
192+
|`parse-context.output-limits.throwOnWriteLimit`
193+
194+
|`maxEmbeddedResources`, `maxEmbeddedCount`
195+
|`parse-context.embedded-limits.maxCount`
196+
197+
|`meta_*` (arbitrary metadata injection)
198+
|_no replacement_ — see below
199+
200+
|`X-Tika-Handler`
201+
|Use an explicit handler path (`/tika/text`, `/rmeta/xml`, `/tika/json/html`, ...)
202+
|===
203+
204+
The `X-Tika-OCR*` and `X-Tika-PDF*` header families were removed earlier in the
205+
4.x line. Parser configuration is now supplied as JSON.
206+
207+
[source,json]
208+
----
209+
{
210+
"parse-context": {
211+
"output-limits": {
212+
"writeLimit": 100000,
213+
"throwOnWriteLimit": false
214+
},
215+
"embedded-limits": {
216+
"maxCount": 10
217+
}
218+
}
219+
}
220+
----
221+
222+
**Migration:** move these settings into your tika-config. For per-request values,
223+
POST to a `/config` endpoint (`/tika/config`, `/tika/config/json`, `/rmeta/config`,
224+
`/meta/config`) with the JSON above as the multipart `config` part; this requires
225+
`allowPerRequestConfig=true`.
226+
227+
[IMPORTANT]
228+
====
229+
Two capabilities are genuinely gone, not relocated.
230+
231+
**Per-request output bounds without `allowPerRequestConfig`.** With the headers
232+
removed and per-request config off by default, a caller can no longer bound the
233+
output of a single request; the limits are whatever the operator configured. If
234+
you relied on clients setting their own `writeLimit`, either enable
235+
`allowPerRequestConfig` or set a server-wide limit.
236+
237+
**Client-supplied metadata (`meta_*`).** Headers prefixed `meta_` were copied
238+
into the returned metadata under the remainder of the header name, with no key
239+
restrictions — so a request could also overwrite keys Tika itself populates.
240+
There is no replacement on the push endpoints; attach provenance on your side of
241+
the call, or use `/pipes`, where the `FetchEmitTuple` carries metadata.
242+
====
243+
244+
Transport headers are unaffected: `Content-Disposition`/`File-Name`,
245+
`Content-Type` and `Content-Length` still describe the payload and still
246+
influence detection.
247+
179248
=== Removed Features
180249
181250
* **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.

docs/modules/ROOT/pages/migration-to-4x/migrating-to-4x.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ If you have build scripts or container images that drop in just the jar, update
4545
In 3.x the default content handler produced XHTML/XML. In 4.x the default is **Markdown** everywhere:
4646

4747
* `tika-app` outputs Markdown by default (was XHTML). Pass `-x`/`--xml`, `-h`/`--html`, or `-t`/`--text` to choose another format.
48-
* `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.
48+
* `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.
4949
* The async/pipes CLI emits Markdown by default (was plain text). Use `--handler x` (etc.) to choose another format.
5050

5151
If you parse the extracted content programmatically and expect XHTML/XML, request it explicitly as shown above (TIKA-4663).

docs/modules/ROOT/pages/pipes/cpu-sizing.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ report `autoCap=user-set in forkedJvmArgs`.
169169
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:
170170

171171
* **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.
172-
* **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.
172+
* **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.
173173
* **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.
174174

175175
This is a default — not a tuning recommendation. To right-size for your specific corpus:

docs/modules/ROOT/pages/using-tika/server/index.adoc

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -143,17 +143,6 @@ the JSON variant, you can also nest a handler — `/tika/json/text`,
143143
envelope; that nested handler accepts the full set (`text`, `html`, `xml`,
144144
`md`, `markdown`, `body`, `ignore`).
145145

146-
==== `X-Tika-Handler` header
147-
148-
For the root `/tika` PUT endpoint you can also pick the handler with a header:
149-
150-
[source,bash]
151-
----
152-
curl -T document.pdf -H "X-Tika-Handler: markdown" http://localhost:9998/tika
153-
----
154-
155-
Accepted values: `text`, `html`, `xml`, `markdown` (or `md`), `body`, `ignore`. The default is `markdown`.
156-
157146
=== Recursive Metadata (`/rmeta`)
158147

159148
Returns metadata for the container document and all embedded documents as a JSON

tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/resource/RecursiveMetadataResource.java

Lines changed: 8 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
package org.apache.tika.server.core.resource;
1818

1919
import static org.apache.tika.server.core.resource.TikaResource.fillMetadata;
20-
import static org.apache.tika.server.core.resource.TikaResource.getWriteLimit;
2120
import static org.apache.tika.server.core.resource.TikaResource.setupContentHandlerFactory;
2221
import static org.apache.tika.server.core.resource.TikaResource.setupContentHandlerFactoryIfNeeded;
2322

@@ -38,7 +37,6 @@
3837
import org.slf4j.Logger;
3938
import org.slf4j.LoggerFactory;
4039

41-
import org.apache.tika.config.EmbeddedLimits;
4240
import org.apache.tika.io.TikaInputStream;
4341
import org.apache.tika.metadata.Metadata;
4442
import org.apache.tika.parser.ParseContext;
@@ -65,41 +63,20 @@ public RecursiveMetadataResource(TikaResource tikaResource) {
6563
*/
6664
public List<Metadata> parseMetadata(TikaInputStream tis, Metadata metadata,
6765
MultivaluedMap<String, String> httpHeaders,
68-
ServerHandlerConfig handlerConfig)
66+
String handlerTypeName)
6967
throws Exception {
7068

7169
final ParseContext context = tikaResource.createParseContext();
7270

7371
fillMetadata(null, metadata, httpHeaders);
7472
TikaResource.logRequest(LOG, "/rmeta", metadata);
7573

76-
// Set up handler factory in context using shared utility
77-
setupContentHandlerFactory(context, handlerConfig.type().toString(), handlerConfig.writeLimit(),
78-
handlerConfig.throwOnWriteLimitReached());
79-
80-
// Set up embedded limits if specified
81-
if (handlerConfig.maxEmbeddedCount() >= 0) {
82-
EmbeddedLimits limits = new EmbeddedLimits();
83-
limits.setMaxCount(handlerConfig.maxEmbeddedCount());
84-
context.set(EmbeddedLimits.class, limits);
85-
}
74+
setupContentHandlerFactory(context, handlerTypeName);
8675

8776
// Filtering is done in child process, no need to filter again
8877
return tikaResource.parseWithPipes(tis, metadata, context, ParseMode.RMETA);
8978
}
9079

91-
static ServerHandlerConfig buildHandlerConfig(MultivaluedMap<String, String> httpHeaders, String handlerTypeName, ParseMode parseMode) {
92-
int maxEmbeddedCount = -1;
93-
// Support both old header name and new for backwards compatibility
94-
if (httpHeaders.containsKey("maxEmbeddedResources")) {
95-
maxEmbeddedCount = Integer.parseInt(httpHeaders.getFirst("maxEmbeddedResources"));
96-
} else if (httpHeaders.containsKey("maxEmbeddedCount")) {
97-
maxEmbeddedCount = Integer.parseInt(httpHeaders.getFirst("maxEmbeddedCount"));
98-
}
99-
return new ServerHandlerConfig(BasicContentHandlerFactory.parseHandlerType(handlerTypeName, DEFAULT_HANDLER_TYPE), parseMode,
100-
getWriteLimit(httpHeaders), maxEmbeddedCount, TikaResource.getThrowOnWriteLimitReached(httpHeaders));
101-
}
102-
10380
/**
10481
* Returns an InputStream that can be deserialized as a list of
10582
* {@link Metadata} objects.
@@ -134,7 +111,7 @@ public Response getMetadataFromMultipart(Attachment att, @PathParam(HANDLER_TYPE
134111
try (TikaInputStream tis = TikaInputStream.get(att.getObject(InputStream.class))) {
135112
tis.getPath(); // Spool to temp file for pipes-based parsing
136113
List<Metadata> metadataList = parseMetadata(tis, Metadata.newInstance(context), att.getHeaders(),
137-
buildHandlerConfig(att.getHeaders(), handlerTypeName, ParseMode.RMETA));
114+
handlerTypeName);
138115
return Response.ok(new MetadataList(metadataList)).build();
139116
}
140117
}
@@ -159,18 +136,14 @@ public Response getMetadataWithConfig(
159136
TikaResource.logRequest(LOG, "/rmeta/config", metadata);
160137

161138
return Response
162-
.ok(parseMetadataWithContext(tis, metadata, httpHeaders.getRequestHeaders(),
163-
buildHandlerConfig(httpHeaders.getRequestHeaders(), null, ParseMode.RMETA),
164-
context))
139+
.ok(parseMetadataWithContext(tis, metadata, null, context))
165140
.build();
166141
}
167142
}
168143

169-
private MetadataList parseMetadataWithContext(TikaInputStream tis, Metadata metadata, MultivaluedMap<String, String> httpHeaders,
170-
ServerHandlerConfig handlerConfig, ParseContext context) throws Exception {
171-
// Set up handler factory in context if not already set using shared utility
172-
setupContentHandlerFactoryIfNeeded(context, handlerConfig.type().toString(),
173-
handlerConfig.writeLimit(), handlerConfig.throwOnWriteLimitReached());
144+
private MetadataList parseMetadataWithContext(TikaInputStream tis, Metadata metadata,
145+
String handlerTypeName, ParseContext context) throws Exception {
146+
setupContentHandlerFactoryIfNeeded(context, handlerTypeName);
174147

175148
// Filtering is done in child process, no need to filter again
176149
List<Metadata> metadataList = tikaResource.parseWithPipes(tis, metadata, context, ParseMode.RMETA);
@@ -210,7 +183,7 @@ public Response getMetadata(InputStream is, @Context HttpHeaders httpHeaders, @P
210183
try (TikaInputStream tis = TikaInputStream.get(is)) {
211184
tis.getPath(); // Spool to temp file for pipes-based parsing
212185
List<Metadata> metadataList = parseMetadata(tis, metadata, httpHeaders.getRequestHeaders(),
213-
buildHandlerConfig(httpHeaders.getRequestHeaders(), handlerTypeName, ParseMode.RMETA));
186+
handlerTypeName);
214187
return Response.ok(new MetadataList(metadataList)).build();
215188
}
216189
}

tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/resource/ServerHandlerConfig.java

Lines changed: 0 additions & 37 deletions
This file was deleted.

0 commit comments

Comments
 (0)