You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tika.apache.org by ta...@apache.org on 2022/04/06 14:50:45 UTC

[tika] branch main updated: TIKA-3714 -- allow specification of fetchername and fetchkey in url parameters in tika-server

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

tallison pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tika.git


The following commit(s) were added to refs/heads/main by this push:
     new 984ce0e77 TIKA-3714 -- allow specification of fetchername and fetchkey in url parameters in tika-server
984ce0e77 is described below

commit 984ce0e776900dfefbf3b956479d4ed832c0c4a6
Author: tallison <ta...@apache.org>
AuthorDate: Wed Apr 6 10:50:31 2022 -0400

    TIKA-3714 -- allow specification of fetchername and fetchkey in url parameters in tika-server
---
 CHANGES.txt                                        |   3 +
 .../server/core/DefaultInputStreamFactory.java     |   7 ++
 .../tika/server/core/FetcherStreamFactory.java     |  30 ++++--
 .../tika/server/core/InputStreamFactory.java       |  15 +++
 .../server/core/resource/DetectorResource.java     |   2 +-
 .../server/core/resource/MetadataResource.java     |   5 +-
 .../core/resource/RecursiveMetadataResource.java   |   2 +-
 .../tika/server/core/resource/TikaResource.java    |  15 +--
 .../server/core/resource/UnpackerResource.java     |   6 +-
 .../org/apache/tika/server/core/CXFTestBase.java   |   9 +-
 .../org/apache/tika/server/core/TikaPipesTest.java |   3 +-
 .../tika/server/core/TikaResourceFetcherTest.java  | 110 +++++++++++++++++++++
 .../tika-config-server-fetcher-template.xml        |  38 +++++++
 .../standard/resource/XMPMetadataResource.java     |   3 +-
 .../apache/tika/server/standard/FetcherTest.java   |  12 +--
 .../apache/tika/server/standard/TikaPipesTest.java |   6 +-
 16 files changed, 230 insertions(+), 36 deletions(-)

diff --git a/CHANGES.txt b/CHANGES.txt
index bc49d9cd3..4bd57be0f 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -9,6 +9,9 @@ Release 2.4.0 - ???
    * Add MetadataWriteFilter capability to improve memory profile in
      Metadata objects (TIKA-3695).
 
+   * Allow specification of fetcherName and fetchKey via query parameters
+     in request URI in tika-server (TIKA-3714).
+
    * Add basic parsers for WARC and WACZ in tika-parsers-standard (TIKA-3697).
 
    * Add detection for Frictionless Data packages and WACZ (TIKA-3696).
diff --git a/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/DefaultInputStreamFactory.java b/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/DefaultInputStreamFactory.java
index 155f7e274..4b6e399be 100644
--- a/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/DefaultInputStreamFactory.java
+++ b/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/DefaultInputStreamFactory.java
@@ -20,6 +20,7 @@ package org.apache.tika.server.core;
 import java.io.IOException;
 import java.io.InputStream;
 import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.UriInfo;
 
 import org.apache.tika.metadata.Metadata;
 
@@ -33,4 +34,10 @@ public class DefaultInputStreamFactory implements InputStreamFactory {
             throws IOException {
         return is;
     }
+
+    @Override
+    public InputStream getInputStream(InputStream is, Metadata metadata, HttpHeaders httpHeaders,
+                                      UriInfo uriInfo) throws IOException {
+        return is;
+    }
 }
diff --git a/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/FetcherStreamFactory.java b/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/FetcherStreamFactory.java
index 2694006e4..dc1a00a13 100644
--- a/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/FetcherStreamFactory.java
+++ b/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/FetcherStreamFactory.java
@@ -19,6 +19,8 @@ package org.apache.tika.server.core;
 import java.io.IOException;
 import java.io.InputStream;
 import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.UriInfo;
 
 import org.apache.commons.lang3.StringUtils;
 
@@ -52,12 +54,13 @@ public class FetcherStreamFactory implements InputStreamFactory {
     }
 
     @Override
-    public InputStream getInputStream(InputStream is, Metadata metadata, HttpHeaders httpHeaders)
-            throws IOException {
-        String fetcherName = httpHeaders.getHeaderString("fetcherName");
-        String fetchKey = httpHeaders.getHeaderString("fetchKey");
-        long fetchRangeStart = getLong(httpHeaders.getHeaderString("fetchRangeStart"));
-        long fetchRangeEnd = getLong(httpHeaders.getHeaderString("fetchRangeEnd"));
+    public InputStream getInputStream(InputStream is, Metadata metadata, HttpHeaders httpHeaders,
+                                      UriInfo uriInfo) throws IOException {
+        MultivaluedMap params = (uriInfo == null) ? null : uriInfo.getQueryParameters();
+        String fetcherName = getParam("fetcherName", httpHeaders, params);
+        String fetchKey = getParam("fetchKey", httpHeaders, params);
+        long fetchRangeStart = getLong(getParam("fetchRangeStart", httpHeaders, params));
+        long fetchRangeEnd = getLong(getParam("fetchRangeEnd", httpHeaders, params));
         if (StringUtils.isBlank(fetcherName) != StringUtils.isBlank(fetchKey)) {
             throw new IOException("Must specify both a 'fetcherName' and a 'fetchKey'. I see: " +
                     " fetcherName:" + fetcherName + " and fetchKey:" + fetchKey);
@@ -93,6 +96,21 @@ public class FetcherStreamFactory implements InputStreamFactory {
         return is;
     }
 
+    private String getParam(String paramName, HttpHeaders httpHeaders, MultivaluedMap uriParams) {
+        if (uriParams == null || ! uriParams.containsKey(paramName)) {
+            return httpHeaders.getHeaderString(paramName);
+        }
+
+        return (String)uriParams.getFirst(paramName);
+    }
+
+    @Override
+    public InputStream getInputStream(InputStream is, Metadata metadata, HttpHeaders httpHeaders)
+            throws IOException {
+        return getInputStream(is, metadata, httpHeaders, null);
+
+    }
+
     /**
      * Tries to parse a long out of the value.  If the val is blank, it returns -1.
      * Throws {@link NumberFormatException}
diff --git a/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/InputStreamFactory.java b/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/InputStreamFactory.java
index 89cfa502b..a1f65c4b2 100644
--- a/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/InputStreamFactory.java
+++ b/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/InputStreamFactory.java
@@ -20,6 +20,7 @@ package org.apache.tika.server.core;
 import java.io.IOException;
 import java.io.InputStream;
 import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.UriInfo;
 
 import org.apache.tika.metadata.Metadata;
 
@@ -31,7 +32,21 @@ import org.apache.tika.metadata.Metadata;
  */
 public interface InputStreamFactory {
 
+    /**
+     * @deprecated use {@link #getInputStream(InputStream, Metadata, HttpHeaders, UriInfo)}
+     * @param is
+     * @param metadata
+     * @param httpHeaders
+     * @return
+     * @throws IOException
+     */
+    @Deprecated
     InputStream getInputStream(InputStream is, Metadata metadata, HttpHeaders httpHeaders)
             throws IOException;
 
+
+    InputStream getInputStream(InputStream is, Metadata metadata, HttpHeaders httpHeaders,
+                               UriInfo uriInfo)
+            throws IOException;
+
 }
diff --git a/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/resource/DetectorResource.java b/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/resource/DetectorResource.java
index c89bf2c4b..3c04acc33 100644
--- a/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/resource/DetectorResource.java
+++ b/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/resource/DetectorResource.java
@@ -63,7 +63,7 @@ public class DetectorResource {
         long taskId = serverStatus.start(ServerStatus.TASK.DETECT, filename, timeoutMillis);
 
         try (TikaInputStream tis = TikaInputStream
-                .get(TikaResource.getInputStream(is, met, httpHeaders))) {
+                .get(TikaResource.getInputStream(is, met, httpHeaders, info))) {
             return TikaResource.getConfig().getDetector().detect(tis, met).toString();
         } catch (IOException e) {
             LOG.warn("Unable to detect MIME type for file. Reason: {} ({})", e.getMessage(),
diff --git a/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/resource/MetadataResource.java b/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/resource/MetadataResource.java
index b26023fe7..00f88426d 100644
--- a/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/resource/MetadataResource.java
+++ b/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/resource/MetadataResource.java
@@ -65,7 +65,8 @@ public class MetadataResource {
                                 @Context UriInfo info) throws Exception {
         Metadata metadata = new Metadata();
         return Response
-                .ok(parseMetadata(TikaResource.getInputStream(is, metadata, httpHeaders), metadata,
+                .ok(parseMetadata(TikaResource.getInputStream(is, metadata, httpHeaders, info),
+                        metadata,
                         httpHeaders.getRequestHeaders(), info)).build();
     }
 
@@ -105,7 +106,7 @@ public class MetadataResource {
         Metadata metadata = new Metadata();
         boolean success = false;
         try {
-            parseMetadata(TikaResource.getInputStream(is, metadata, httpHeaders), metadata,
+            parseMetadata(TikaResource.getInputStream(is, metadata, httpHeaders, info), metadata,
                     httpHeaders.getRequestHeaders(), info);
             // once we've parsed the document successfully, we should use NOT_FOUND
             // if we did not see the field
diff --git a/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/resource/RecursiveMetadataResource.java b/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/resource/RecursiveMetadataResource.java
index 648baf008..545d4ae2c 100644
--- a/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/resource/RecursiveMetadataResource.java
+++ b/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/resource/RecursiveMetadataResource.java
@@ -177,7 +177,7 @@ public class RecursiveMetadataResource {
             throws Exception {
         Metadata metadata = new Metadata();
         return Response.ok(parseMetadataToMetadataList(
-                TikaResource.getInputStream(is, metadata, httpHeaders), metadata,
+                TikaResource.getInputStream(is, metadata, httpHeaders, info), metadata,
                 httpHeaders.getRequestHeaders(), info,
                 buildHandlerConfig(httpHeaders.getRequestHeaders(), handlerTypeName,
                         HandlerConfig.PARSE_MODE.RMETA))).build();
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 90d33524b..56fbb2eae 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
@@ -153,9 +153,9 @@ public class TikaResource {
     }
 
     public static InputStream getInputStream(InputStream is, Metadata metadata,
-                                             HttpHeaders headers) {
+                                             HttpHeaders headers, UriInfo uriInfo) {
         try {
-            return INPUTSTREAM_FACTORY.getInputStream(is, metadata, headers);
+            return INPUTSTREAM_FACTORY.getInputStream(is, metadata, headers, uriInfo);
         } catch (IOException e) {
             throw new TikaServerParseException(e);
         }
@@ -473,7 +473,7 @@ public class TikaResource {
     public StreamingOutput getText(final InputStream is, @Context HttpHeaders httpHeaders,
                                    @Context final UriInfo info) {
         final Metadata metadata = new Metadata();
-        return produceText(getInputStream(is, metadata, httpHeaders), metadata,
+        return produceText(getInputStream(is, metadata, httpHeaders, info), metadata,
                 httpHeaders.getRequestHeaders(), info);
     }
 
@@ -515,7 +515,7 @@ public class TikaResource {
     public StreamingOutput getHTML(final InputStream is, @Context HttpHeaders httpHeaders,
                                    @Context final UriInfo info) {
         Metadata metadata = new Metadata();
-        return produceOutput(getInputStream(is, metadata, httpHeaders), metadata,
+        return produceOutput(getInputStream(is, metadata, httpHeaders, info), metadata,
                 httpHeaders.getRequestHeaders(), info, "html");
     }
 
@@ -536,7 +536,7 @@ public class TikaResource {
     public StreamingOutput getXML(final InputStream is, @Context HttpHeaders httpHeaders,
                                   @Context final UriInfo info) {
         Metadata metadata = new Metadata();
-        return produceOutput(getInputStream(is, metadata, httpHeaders), metadata,
+        return produceOutput(getInputStream(is, metadata, httpHeaders, info), metadata,
                 httpHeaders.getRequestHeaders(), info, "xml");
     }
 
@@ -551,7 +551,8 @@ public class TikaResource {
                                                      String handlerTypeName)
             throws IOException, TikaException {
         Metadata metadata = new Metadata();
-        parseToMetadata(getInputStream(att.getObject(InputStream.class), metadata, httpHeaders),
+        parseToMetadata(getInputStream(
+                att.getObject(InputStream.class), metadata, httpHeaders, info),
                 metadata, preparePostHeaderMap(att, httpHeaders), info, handlerTypeName);
         TikaResource.getConfig().getMetadataFilter().filter(metadata);
         return metadata;
@@ -567,7 +568,7 @@ public class TikaResource {
                                                String handlerTypeName)
             throws IOException, TikaException {
         Metadata metadata = new Metadata();
-        parseToMetadata(getInputStream(is, metadata, httpHeaders), metadata,
+        parseToMetadata(getInputStream(is, metadata, httpHeaders, info), metadata,
                 httpHeaders.getRequestHeaders(), info, handlerTypeName);
         TikaResource.getConfig().getMetadataFilter().filter(metadata);
         return metadata;
diff --git a/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/resource/UnpackerResource.java b/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/resource/UnpackerResource.java
index 7fbb800fb..837dcdebd 100644
--- a/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/resource/UnpackerResource.java
+++ b/tika-server/tika-server-core/src/main/java/org/apache/tika/server/core/resource/UnpackerResource.java
@@ -96,7 +96,8 @@ public class UnpackerResource {
     @Produces({"application/zip", "application/x-tar"})
     public Map<String, byte[]> unpack(InputStream is, @Context HttpHeaders httpHeaders,
                                       @Context UriInfo info) throws Exception {
-        return process(TikaResource.getInputStream(is, new Metadata(), httpHeaders), httpHeaders,
+        return process(TikaResource.getInputStream(is, new Metadata(), httpHeaders, info),
+                httpHeaders,
                 info, false);
     }
 
@@ -105,7 +106,8 @@ public class UnpackerResource {
     @Produces({"application/zip", "application/x-tar"})
     public Map<String, byte[]> unpackAll(InputStream is, @Context HttpHeaders httpHeaders,
                                          @Context UriInfo info) throws Exception {
-        return process(TikaResource.getInputStream(is, new Metadata(), httpHeaders), httpHeaders,
+        return process(TikaResource.getInputStream(is, new Metadata(), httpHeaders, info),
+                httpHeaders,
                 info, true);
     }
 
diff --git a/tika-server/tika-server-core/src/test/java/org/apache/tika/server/core/CXFTestBase.java b/tika-server/tika-server-core/src/test/java/org/apache/tika/server/core/CXFTestBase.java
index 7239421a2..fbe8042f3 100644
--- a/tika-server/tika-server-core/src/test/java/org/apache/tika/server/core/CXFTestBase.java
+++ b/tika-server/tika-server-core/src/test/java/org/apache/tika/server/core/CXFTestBase.java
@@ -84,7 +84,7 @@ public abstract class CXFTestBase {
         return new ByteArrayInputStream(out.toByteArray());
     }
 
-    protected static String getStringFromInputStream(InputStream in) throws Exception {
+    protected static String getStringFromInputStream(InputStream in) throws IOException {
         return IOUtils.toString(in, UTF_8);
     }
 
@@ -105,7 +105,8 @@ public abstract class CXFTestBase {
         TikaResource.init(tika, tikaServerConfig,
                 new CommonsDigester(DIGESTER_READ_LIMIT, "md5," +
                         "sha1:32"),
-                getInputStreamFactory(tika), new ServerStatus("", 0, true));
+                getInputStreamFactory(getTikaConfigInputStream()),
+                new ServerStatus("", 0, true));
         JAXRSServerFactoryBean sf = new JAXRSServerFactoryBean();
         //set compression interceptors
         sf.setOutInterceptors(Collections.singletonList(new GZIPOutInterceptor()));
@@ -131,11 +132,11 @@ public abstract class CXFTestBase {
         return tikaServerConfig;
     }
 
-    protected InputStreamFactory getInputStreamFactory(TikaConfig tikaConfig) {
+    protected InputStreamFactory getInputStreamFactory(InputStream tikaConfig) {
         return new DefaultInputStreamFactory();
     }
 
-    protected InputStream getTikaConfigInputStream() {
+    protected InputStream getTikaConfigInputStream() throws IOException {
         return new ByteArrayInputStream(new String(
                 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + "<properties>\n" +
                         "    <parsers>\n" +
diff --git a/tika-server/tika-server-core/src/test/java/org/apache/tika/server/core/TikaPipesTest.java b/tika-server/tika-server-core/src/test/java/org/apache/tika/server/core/TikaPipesTest.java
index 837c894c5..d760dae1d 100644
--- a/tika-server/tika-server-core/src/test/java/org/apache/tika/server/core/TikaPipesTest.java
+++ b/tika-server/tika-server-core/src/test/java/org/apache/tika/server/core/TikaPipesTest.java
@@ -48,7 +48,6 @@ import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 
-import org.apache.tika.config.TikaConfig;
 import org.apache.tika.exception.TikaConfigException;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.metadata.TikaCoreProperties;
@@ -169,7 +168,7 @@ public class TikaPipesTest extends CXFTestBase {
     }
 
     @Override
-    protected InputStreamFactory getInputStreamFactory(TikaConfig tikaConfig) {
+    protected InputStreamFactory getInputStreamFactory(InputStream tikaConfigInputStream) {
         return new FetcherStreamFactory(FETCHER_MANAGER);
     }
 
diff --git a/tika-server/tika-server-core/src/test/java/org/apache/tika/server/core/TikaResourceFetcherTest.java b/tika-server/tika-server-core/src/test/java/org/apache/tika/server/core/TikaResourceFetcherTest.java
new file mode 100644
index 000000000..93dab810b
--- /dev/null
+++ b/tika-server/tika-server-core/src/test/java/org/apache/tika/server/core/TikaResourceFetcherTest.java
@@ -0,0 +1,110 @@
+/*
+ * 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.core;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URISyntaxException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.List;
+import javax.ws.rs.core.MultivaluedHashMap;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+
+import org.apache.cxf.jaxrs.JAXRSServerFactoryBean;
+import org.apache.cxf.jaxrs.client.WebClient;
+import org.apache.cxf.jaxrs.lifecycle.SingletonResourceProvider;
+import org.junit.jupiter.api.Test;
+
+import org.apache.tika.exception.TikaConfigException;
+import org.apache.tika.io.TikaInputStream;
+import org.apache.tika.pipes.fetcher.FetcherManager;
+import org.apache.tika.server.core.resource.TikaResource;
+import org.apache.tika.server.core.writer.JSONMessageBodyWriter;
+
+public class TikaResourceFetcherTest extends CXFTestBase {
+
+    private static final String TIKA_PATH = "/tika";
+
+
+    @Override
+    protected void setUpResources(JAXRSServerFactoryBean sf) {
+        sf.setResourceClasses(TikaResource.class);
+        sf.setResourceProvider(TikaResource.class,
+                new SingletonResourceProvider(new TikaResource()));
+    }
+
+    @Override
+    protected void setUpProviders(JAXRSServerFactoryBean sf) {
+        List<Object> providers = new ArrayList<>();
+        providers.add(new TikaServerParseExceptionMapper(false));
+        providers.add(new JSONMessageBodyWriter());
+        sf.setProviders(providers);
+    }
+
+    @Override
+    protected InputStream getTikaConfigInputStream() throws IOException {
+        Path inputDir = null;
+        try {
+            inputDir = Paths.get(
+                    TikaResourceFetcherTest.class.getResource("/test-documents/").toURI());
+        } catch (URISyntaxException e) {
+            throw new RuntimeException(e);
+        }
+        String configXML = getStringFromInputStream(
+                TikaResourceFetcherTest.class.getResourceAsStream(
+                        "/configs/tika-config-server-fetcher-template.xml"));
+        configXML = configXML.replaceAll("\\$\\{FETCHER_BASE_PATH\\}",
+                inputDir.toAbsolutePath().toString());
+
+        configXML = configXML.replaceAll("\\$\\{PORT\\}", "9998");
+        return new ByteArrayInputStream(configXML.getBytes(StandardCharsets.UTF_8));
+    }
+
+    @Override
+    protected InputStreamFactory getInputStreamFactory(InputStream is) {
+        try (TikaInputStream tis = TikaInputStream.get(is)) {
+            FetcherManager fetcherManager = FetcherManager.load(tis.getPath());
+            return new FetcherStreamFactory(fetcherManager);
+        } catch (IOException | TikaConfigException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @Test
+    public void testHeader() throws Exception {
+        MultivaluedMap<String, String> map = new MultivaluedHashMap<>();
+        map.putSingle("fetcherName", "fsf");
+        map.putSingle("fetchKey", "mock/hello_world.xml");
+        Response response =
+                WebClient.create(endPoint + TIKA_PATH).headers(map).accept("text/xml").put(null);
+        String xml = getStringFromInputStream((InputStream) response.getEntity());
+        assertContains("hello world", xml);
+    }
+
+    @Test
+    public void testQueryPart() throws Exception {
+        Response response = WebClient.create(endPoint + TIKA_PATH).query("fetcherName", "fsf")
+                .query("fetchKey", "mock/hello_world.xml").accept("text/xml").put(null);
+        String xml = getStringFromInputStream((InputStream) response.getEntity());
+        assertContains("hello world", xml);
+    }
+}
diff --git a/tika-server/tika-server-core/src/test/resources/configs/tika-config-server-fetcher-template.xml b/tika-server/tika-server-core/src/test/resources/configs/tika-config-server-fetcher-template.xml
new file mode 100644
index 000000000..473e9499c
--- /dev/null
+++ b/tika-server/tika-server-core/src/test/resources/configs/tika-config-server-fetcher-template.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+-->
+<properties>
+  <fetchers>
+    <fetcher class="org.apache.tika.pipes.fetcher.fs.FileSystemFetcher">
+      <params>
+        <name>fsf</name>
+        <basePath>${FETCHER_BASE_PATH}</basePath>
+      </params>
+    </fetcher>
+  </fetchers>
+  <server>
+    <params>
+      <port>${PORT}</port>
+      <taskTimeoutMillis>54321</taskTimeoutMillis>
+      <enableUnsecureFeatures>true</enableUnsecureFeatures>
+      <noFork>true</noFork>
+      <endpoints>
+        <endpoint>tika</endpoint>
+      </endpoints>
+    </params>
+  </server>
+</properties>
diff --git a/tika-server/tika-server-standard/src/main/java/org/apache/tika/server/standard/resource/XMPMetadataResource.java b/tika-server/tika-server-standard/src/main/java/org/apache/tika/server/standard/resource/XMPMetadataResource.java
index aea81e81d..da130d206 100644
--- a/tika-server/tika-server-standard/src/main/java/org/apache/tika/server/standard/resource/XMPMetadataResource.java
+++ b/tika-server/tika-server-standard/src/main/java/org/apache/tika/server/standard/resource/XMPMetadataResource.java
@@ -63,7 +63,8 @@ public class XMPMetadataResource extends MetadataResource implements TikaServerR
                                 @Context UriInfo info) throws Exception {
         Metadata metadata = new Metadata();
         return Response
-                .ok(parseMetadata(TikaResource.getInputStream(is, metadata, httpHeaders), metadata,
+                .ok(parseMetadata(TikaResource.getInputStream(is, metadata, httpHeaders, info),
+                        metadata,
                         httpHeaders.getRequestHeaders(), info)).build();
     }
 }
diff --git a/tika-server/tika-server-standard/src/test/java/org/apache/tika/server/standard/FetcherTest.java b/tika-server/tika-server-standard/src/test/java/org/apache/tika/server/standard/FetcherTest.java
index b22a7c9d3..63d0785d4 100644
--- a/tika-server/tika-server-standard/src/test/java/org/apache/tika/server/standard/FetcherTest.java
+++ b/tika-server/tika-server-standard/src/test/java/org/apache/tika/server/standard/FetcherTest.java
@@ -23,8 +23,6 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.Reader;
-import java.nio.file.Path;
-import java.nio.file.Paths;
 import java.util.ArrayList;
 import java.util.List;
 import javax.ws.rs.core.Response;
@@ -36,7 +34,7 @@ import org.apache.cxf.jaxrs.lifecycle.SingletonResourceProvider;
 import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Test;
 
-import org.apache.tika.config.TikaConfig;
+import org.apache.tika.io.TikaInputStream;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.metadata.TikaCoreProperties;
 import org.apache.tika.metadata.serialization.JsonMetadataList;
@@ -76,11 +74,9 @@ public class FetcherTest extends CXFTestBase {
     }
 
     @Override
-    protected InputStreamFactory getInputStreamFactory(TikaConfig tikaConfig) {
-        try {
-            Path configPath = Paths.get(
-                    getClass().getResource("/config/tika-config-url-fetcher.xml").toURI());
-            FetcherManager fetcherManager = FetcherManager.load(configPath);
+    protected InputStreamFactory getInputStreamFactory(InputStream tikaConfigInputStream) {
+        try (TikaInputStream tis = TikaInputStream.get(tikaConfigInputStream)) {
+            FetcherManager fetcherManager = FetcherManager.load(tis.getPath());
             return new FetcherStreamFactory(fetcherManager);
         } catch (Exception e) {
             throw new RuntimeException(e);
diff --git a/tika-server/tika-server-standard/src/test/java/org/apache/tika/server/standard/TikaPipesTest.java b/tika-server/tika-server-standard/src/test/java/org/apache/tika/server/standard/TikaPipesTest.java
index 282098c10..03eab2b35 100644
--- a/tika-server/tika-server-standard/src/test/java/org/apache/tika/server/standard/TikaPipesTest.java
+++ b/tika-server/tika-server-standard/src/test/java/org/apache/tika/server/standard/TikaPipesTest.java
@@ -42,7 +42,6 @@ import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 
-import org.apache.tika.config.TikaConfig;
 import org.apache.tika.exception.TikaConfigException;
 import org.apache.tika.metadata.Metadata;
 import org.apache.tika.metadata.TikaCoreProperties;
@@ -95,6 +94,8 @@ public class TikaPipesTest extends CXFTestBase {
         TIKA_PIPES_LOG4j2_PATH = Files.createTempFile(TMP_DIR, "log4j2-", ".xml");
         Files.copy(TikaPipesTest.class.getResourceAsStream("/log4j2.xml"), TIKA_PIPES_LOG4j2_PATH,
                 StandardCopyOption.REPLACE_EXISTING);
+
+        //TODO: templatify this config
         TIKA_CONFIG_XML =
                 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + "<properties>" + "<fetchers>" +
                         "<fetcher class=\"org.apache.tika.pipes.fetcher.fs.FileSystemFetcher\">" +
@@ -157,7 +158,8 @@ public class TikaPipesTest extends CXFTestBase {
     }
 
     @Override
-    protected InputStreamFactory getInputStreamFactory(TikaConfig tikaConfig) {
+    protected InputStreamFactory getInputStreamFactory(InputStream is) {
+        //TODO: fix this to read from the is
         return new FetcherStreamFactory(FETCHER_MANAGER);
     }