Skip to content

Commit c45f648

Browse files
authored
TIKA-4808: tika-server sends only request deltas to the pipes worker (#3034)
1 parent d5f45ec commit c45f648

10 files changed

Lines changed: 384 additions & 75 deletions

File tree

CHANGES.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,13 @@ Release 4.0.0 - ???
138138
* tika-server: /meta now runs through the same pipes-backed parser as the
139139
other extraction endpoints (TIKA-4809).
140140

141+
* tika-server requests now carry only their own parse-context entries to the
142+
forked worker, which supplies the config defaults itself. Previously the
143+
server sent its config's parse-context along with every request, so the
144+
worker -- which clamps request-supplied timeout limits but trusts its own
145+
config's -- treated the operator's timeout-limits as caller input and
146+
clamped them at pipes.maxTotalTaskTimeoutMillis (TIKA-4808).
147+
141148
* tika-grpc's fetchAndParseServerSideStreaming now completes the call
142149
after delivering its reply, instead of leaving the client waiting
143150
for a terminal signal that never came (TIKA-4804).

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,8 @@ public DetectorResource(ServerStatus serverStatus, TikaResource tikaResource) {
5454
@Consumes("*/*")
5555
@Produces("text/plain")
5656
public String detect(final InputStream is, @Context HttpHeaders httpHeaders, @Context final UriInfo info) {
57-
ParseContext parseContext = tikaResource.createParseContext();
58-
Metadata met = Metadata.newInstance(parseContext);
57+
ParseContext parseContext = tikaResource.createRequestContext();
58+
Metadata met = tikaResource.newRequestMetadata();
5959

6060
String filename = TikaResource.detectFilename(httpHeaders.getRequestHeaders());
6161
LOG.debug("Detecting media type for Filename: {}", filename);

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

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,11 @@ public MetadataResource(TikaResource tikaResource) {
6363
protected MetadataResource() {
6464
}
6565

66+
/** For subclasses in other modules; they need it for request contexts and metadata. */
67+
protected TikaResource getTikaResource() {
68+
return tikaResource;
69+
}
70+
6671
protected void setTikaResource(TikaResource tikaResource) {
6772
this.tikaResource = tikaResource;
6873
}
@@ -72,10 +77,10 @@ protected void setTikaResource(TikaResource tikaResource) {
7277
@Produces({"application/json", "text/csv"})
7378
@Path("form")
7479
public Response getMetadataFromMultipart(Attachment att, @Context UriInfo info) throws Exception {
75-
ParseContext context = tikaResource.createParseContext();
80+
ParseContext context = tikaResource.createRequestContext();
7681
try (TikaInputStream tis = TikaInputStream.get(att.getObject(InputStream.class))) {
7782
return Response
78-
.ok(parseMetadata(tis, Metadata.newInstance(context), att.getHeaders(), context))
83+
.ok(parseMetadata(tis, tikaResource.newRequestMetadata(), att.getHeaders(), context))
7984
.build();
8085
}
8186
}
@@ -93,8 +98,8 @@ public Response getMetadataWithConfig(
9398
@Context HttpHeaders httpHeaders) throws Exception {
9499

95100
// Load default context from config, then overlay with request config
96-
ParseContext context = tikaResource.createParseContext();
97-
Metadata metadata = Metadata.newInstance(context);
101+
ParseContext context = tikaResource.createRequestContext();
102+
Metadata metadata = tikaResource.newRequestMetadata();
98103
try (TikaInputStream tis = tikaResource.setupMultipartConfig(attachments, metadata, context)) {
99104
TikaResource.logRequest(LOG, "/meta/config", metadata);
100105
// Null headers: multipart request headers describe the envelope and would
@@ -106,8 +111,8 @@ public Response getMetadataWithConfig(
106111
@PUT
107112
@Produces({"application/json", "text/csv"})
108113
public Response getMetadata(InputStream is, @Context HttpHeaders httpHeaders, @Context UriInfo info) throws Exception {
109-
ParseContext context = tikaResource.createParseContext();
110-
Metadata metadata = Metadata.newInstance(context);
114+
ParseContext context = tikaResource.createRequestContext();
115+
Metadata metadata = tikaResource.newRequestMetadata();
111116
try (TikaInputStream tis = TikaInputStream.get(is)) {
112117
return Response
113118
.ok(parseMetadata(tis, metadata, httpHeaders.getRequestHeaders(), context))
@@ -140,10 +145,10 @@ public Response getMetadata(InputStream is, @Context HttpHeaders httpHeaders, @C
140145
@Path("{field}")
141146
@Produces({"application/json", "text/csv", "text/plain"})
142147
public Response getMetadataField(InputStream is, @Context HttpHeaders httpHeaders, @Context UriInfo info, @PathParam("field") String field) throws Exception {
143-
ParseContext context = tikaResource.createParseContext();
148+
ParseContext context = tikaResource.createRequestContext();
144149
Metadata metadata;
145150
try (TikaInputStream tis = TikaInputStream.get(is)) {
146-
metadata = parseMetadata(tis, Metadata.newInstance(context), httpHeaders.getRequestHeaders(), context);
151+
metadata = parseMetadata(tis, tikaResource.newRequestMetadata(), httpHeaders.getRequestHeaders(), context);
147152
}
148153

149154
String containerException = metadata.get(TikaCoreProperties.CONTAINER_EXCEPTION);
@@ -191,7 +196,7 @@ protected Metadata parseMetadata(TikaInputStream tis, Metadata metadata, Multiva
191196
TikaResource.logRequest(LOG, "/meta", metadata);
192197
List<Metadata> metadataList = tikaResource.parseWithPipes(tis, metadata, context, ParseMode.RMETA);
193198
if (metadataList.isEmpty()) {
194-
return Metadata.newInstance(context);
199+
return tikaResource.newRequestMetadata();
195200
}
196201
return metadataList.get(0);
197202
}

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

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -372,12 +372,10 @@ private List<Metadata> processResult(PipesResult result) {
372372
LOG.debug("Parse returned empty result, status: {}", result.status());
373373
String message = result.message();
374374
if (message != null && !message.isEmpty()) {
375-
// Plain ParseContext, not TikaResource.createParseContext() -- this class is
375+
// Unbounded Metadata: this holds only our own error message, and this class is
376376
// constructed before TikaResource (which takes it as a constructor arg), so
377-
// depending back on TikaResource here would be circular. Only used to build
378-
// an error-result Metadata object; no actual parsing happens on this path.
379-
ParseContext context = new ParseContext();
380-
Metadata errorMetadata = Metadata.newInstance(context);
377+
// reaching back for the configured write limiter would be circular.
378+
Metadata errorMetadata = new Metadata();
381379
errorMetadata.add(TikaCoreProperties.CONTAINER_EXCEPTION, message);
382380
return Collections.singletonList(errorMetadata);
383381
}

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

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +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.setupContentHandlerFactory;
21-
import static org.apache.tika.server.core.resource.TikaResource.setupContentHandlerFactoryIfNeeded;
2220

2321
import java.io.InputStream;
2422
import java.util.List;
@@ -66,12 +64,12 @@ public List<Metadata> parseMetadata(TikaInputStream tis, Metadata metadata,
6664
String handlerTypeName)
6765
throws Exception {
6866

69-
final ParseContext context = tikaResource.createParseContext();
67+
final ParseContext context = tikaResource.createRequestContext();
7068

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

74-
setupContentHandlerFactory(context, handlerTypeName);
72+
tikaResource.setupContentHandlerFactory(context, handlerTypeName);
7573

7674
// Filtering is done in child process, no need to filter again
7775
return tikaResource.parseWithPipes(tis, metadata, context, ParseMode.RMETA);
@@ -107,9 +105,8 @@ public List<Metadata> parseMetadata(TikaInputStream tis, Metadata metadata,
107105
@Produces({"application/json"})
108106
@Path("form{" + HANDLER_TYPE_PARAM + " : (\\w+)?}")
109107
public Response getMetadataFromMultipart(Attachment att, @PathParam(HANDLER_TYPE_PARAM) String handlerTypeName) throws Exception {
110-
ParseContext context = tikaResource.createParseContext();
111108
try (TikaInputStream tis = TikaInputStream.get(att.getObject(InputStream.class))) {
112-
List<Metadata> metadataList = parseMetadata(tis, Metadata.newInstance(context), att.getHeaders(),
109+
List<Metadata> metadataList = parseMetadata(tis, tikaResource.newRequestMetadata(), att.getHeaders(),
113110
handlerTypeName);
114111
return Response.ok(new MetadataList(metadataList)).build();
115112
}
@@ -128,8 +125,8 @@ public Response getMetadataWithConfig(
128125
List<Attachment> attachments,
129126
@Context HttpHeaders httpHeaders) throws Exception {
130127

131-
ParseContext context = tikaResource.createParseContext();
132-
Metadata metadata = Metadata.newInstance(context);
128+
ParseContext context = tikaResource.createRequestContext();
129+
Metadata metadata = tikaResource.newRequestMetadata();
133130
try (TikaInputStream tis = tikaResource.setupMultipartConfig(attachments, metadata, context)) {
134131

135132
TikaResource.logRequest(LOG, "/rmeta/config", metadata);
@@ -142,7 +139,7 @@ public Response getMetadataWithConfig(
142139

143140
private MetadataList parseMetadataWithContext(TikaInputStream tis, Metadata metadata,
144141
String handlerTypeName, ParseContext context) throws Exception {
145-
setupContentHandlerFactoryIfNeeded(context, handlerTypeName);
142+
tikaResource.setupContentHandlerFactoryIfNeeded(context, handlerTypeName);
146143

147144
// Filtering is done in child process, no need to filter again
148145
List<Metadata> metadataList = tikaResource.parseWithPipes(tis, metadata, context, ParseMode.RMETA);
@@ -177,8 +174,7 @@ private MetadataList parseMetadataWithContext(TikaInputStream tis, Metadata meta
177174
@Produces("application/json")
178175
@Path("{" + HANDLER_TYPE_PARAM + " : (\\w+)?}")
179176
public Response getMetadata(InputStream is, @Context HttpHeaders httpHeaders, @PathParam(HANDLER_TYPE_PARAM) String handlerTypeName) throws Exception {
180-
ParseContext context = tikaResource.createParseContext();
181-
Metadata metadata = Metadata.newInstance(context);
177+
Metadata metadata = tikaResource.newRequestMetadata();
182178
try (TikaInputStream tis = TikaInputStream.get(is)) {
183179
List<Metadata> metadataList = parseMetadata(tis, metadata, httpHeaders.getRequestHeaders(),
184180
handlerTypeName);

0 commit comments

Comments
 (0)