Tika-Server Integration Testing
- Setup
- Part 1: Default Mode Tests
- Test 1: GET /version
- Test 2: PUT /detect
- Test 3: PUT /tika/text
- Test 4: PUT /tika/html
- Test 5: PUT /tika/xml
- Test 6: PUT /tika/json
- Test 7: PUT /meta
- Test 8: PUT /meta/{field}
- Test 9: PUT /rmeta
- Test 10: PUT /rmeta/text
- Test 11: PUT /language
- Test 12: PUT /unpack/all
- Test 13: GET /parsers
- Test 14: GET /detectors
- Test 15: GET /mime-types
- Test 16: POST /meta/form
- Test 17: POST /rmeta/form
- Test 18: Config Endpoints Blocked (Default Mode)
- Test 18b:
/pipesand/asyncRequire allowPipes
- Part 2: Tests with allowPipes / allowPerRequestConfig
- Server Options
- Headers
- Error Handling
- Cleanup
- Usability Test Results
- Known Issues
- Quick Reference
- Implementation Notes
Integration tests for tika-server to be run from a distribution ZIP.
Setup
# Create test directory
mkdir -p /tmp/tika-server-test
cd /tmp/tika-server-test
# Copy and extract distribution
cp /path/to/tika-server-standard-4.0.0-SNAPSHOT.zip .
unzip tika-server-standard-4.0.0-SNAPSHOT.zip
# Copy test files
cp /path/to/test-documents/testPDF.pdf .
cp /path/to/test-documents/testHTML.html .
cp /path/to/test-documents/test_recursive_embedded.docx .
Part 1: Default Mode Tests
Start server in default mode (config endpoints disabled):
java -jar tika-server-standard-4.0.0-SNAPSHOT.jar --port 9998 &
sleep 8
curl -s http://localhost:9998/version
Test 2: PUT /detect
curl -s -X PUT -T testPDF.pdf http://localhost:9998/detect
Expected: application/pdf
Test 3: PUT /tika/text
curl -s -X PUT -T testPDF.pdf http://localhost:9998/tika/text
Expected: Plain text content extracted from PDF.
Test 4: PUT /tika/html
curl -s -X PUT -T testPDF.pdf http://localhost:9998/tika/html
Expected: HTML with metadata in <meta> tags and content in <body>.
Test 5: PUT /tika/xml
curl -s -X PUT -T testPDF.pdf http://localhost:9998/tika/xml
Expected: XHTML content (starts with <html xmlns=…>).
Test 6: PUT /tika/json
curl -s -X PUT -T testPDF.pdf http://localhost:9998/tika/json
Expected: JSON object with metadata and tk:content field.
Test 7: PUT /meta
curl -s -X PUT -H "Accept: application/json" -T testPDF.pdf http://localhost:9998/meta
Expected: JSON object with metadata only (no content).
Test 8: PUT /meta/{field}
curl -s -X PUT -T testPDF.pdf http://localhost:9998/meta/Content-Type
Expected: JSON containing only the requested field: {"Content-Type":"application/pdf"}
(the header-less default is JSON; add -H "Accept: text/csv" for Content-Type,application/pdf)
Test 9: PUT /rmeta
curl -s -X PUT -T test_recursive_embedded.docx http://localhost:9998/rmeta
Expected: JSON array with metadata for main document and all embedded documents.
Test 10: PUT /rmeta/text
curl -s -X PUT -T test_recursive_embedded.docx http://localhost:9998/rmeta/text
Expected: JSON array with ToTextContentHandler content.
Test 11: PUT /language
curl -s -X PUT -T testPDF.pdf http://localhost:9998/language
Expected: An ISO 639 code, i.e. 2-3 lowercase letters. Do not assert a particular
language here: testPDF.pdf carries too little text for detection to be reliable, which
is why run-uat.sh matches ^[a-z]{2,3}$ rather than a specific code.
Test 12: PUT /unpack/all
curl -s -X PUT -T test_recursive_embedded.docx http://localhost:9998/unpack/all -o /tmp/unpack.zip
unzip -l /tmp/unpack.zip
Expected: ZIP file containing the extracted embedded files, a *.metadata.json entry
per file, and the original container document.
Test 13: GET /parsers
curl -s -H "Accept: text/plain" http://localhost:9998/parsers
Expected: Hierarchical list of available parsers.
Test 14: GET /detectors
curl -s -H "Accept: text/plain" http://localhost:9998/detectors
Expected: List of available detectors.
Test 15: GET /mime-types
curl -s -H "Accept: application/json" http://localhost:9998/mime-types
Expected: JSON object with all known MIME types.
Test 16: POST /meta/form
curl -s -X POST -F "upload=@testPDF.pdf" -H "Accept: application/json" http://localhost:9998/meta/form
Expected: JSON metadata from multipart form upload.
Test 17: POST /rmeta/form
curl -s -X POST -F "upload=@test_recursive_embedded.docx" http://localhost:9998/rmeta/form
Expected: JSON array with recursive metadata from multipart upload.
Test 18: Config Endpoints Blocked (Default Mode)
curl -s -w "\nHTTP Status: %{http_code}\n" -X POST -F "file=@testPDF.pdf" http://localhost:9998/meta/config
curl -s -w "\nHTTP Status: %{http_code}\n" -X POST -F "file=@testPDF.pdf" http://localhost:9998/rmeta/config
curl -s -w "\nHTTP Status: %{http_code}\n" -X POST -F "file=@testPDF.pdf" http://localhost:9998/tika/config
curl -s -w "\nHTTP Status: %{http_code}\n" -X POST -F "file=@testPDF.pdf" http://localhost:9998/unpack/all/config
Expected: All return HTTP 403 with message: "Config endpoints are disabled. Set allowPerRequestConfig=true in server config."
The unpack config-variant path is /unpack/all/config; there is no /unpack/config
(the {id} path template requires a leading slash, so /unpack/config returns 404, not 403).
The second enforcement point — a multipart config part on a parse endpoint that accepts one
(e.g. POST /unpack with -F 'config=…') — is also rejected with HTTP 403 and the message
"Per-request configuration is disabled. Set allowPerRequestConfig=true in server config."
|
Test 18b: /pipes and /async Require allowPipes
cat > tika-config-pipes-no-flags.json << 'EOF'
{
"server": {"port": 9998, "endpoints": ["tika", "pipes"]},
"pipes": {"numClients": 2},
"plugin-roots": "/tmp/tika-server-test/plugins"
}
EOF
java -jar tika-server-standard-4.0.0-SNAPSHOT.jar -c tika-config-pipes-no-flags.json
Expected: The server refuses to start, failing with a TikaConfigException stating that the pipes endpoint requires allowPipes to be true. The same applies to async. /status is not gated — listing status under endpoints is enough.
Part 2: Tests with allowPipes / allowPerRequestConfig
Stop the default server and create a config file:
pkill -f "tika-server-standard-4.0.0-SNAPSHOT.jar"
cat > tika-config-capabilities.json << 'EOF'
{
"server": {
"port": 9998,
"host": "localhost",
"allowPipes": true,
"allowPerRequestConfig": true
},
"parsers": [
{"default-parser": {}}
],
"plugin-roots": "/tmp/tika-server-test/plugins"
}
EOF
java -jar tika-server-standard-4.0.0-SNAPSHOT.jar -c tika-config-capabilities.json &
sleep 10
curl -s http://localhost:9998/version
Test 19: POST /meta/config
curl -s -X POST -F "file=@testPDF.pdf" -H "Accept: application/json" http://localhost:9998/meta/config
Expected: JSON metadata.
Test 20: POST /meta/config with custom parser config
curl -s -X POST -F "file=@testPDF.pdf" \
-F 'config={"pdf-parser":{"ocr":{"strategy":"NO_OCR"}}}' \
-H "Accept: application/json" \
http://localhost:9998/meta/config
Expected: JSON metadata with custom PDF parser config applied.
The per-request config must use the top-level self-configuring form
({"pdf-parser":{…}}), NOT the server-config {"parsers":[{"pdf-parser":{…}}]} wrapper.
Under the TIKA-4763 wire restriction, a Parser/Detector name nested inside a parsers
array is rejected (only top-level self-configuring keys such as pdf-parser are honored at
request time). Supplying the nested form currently returns HTTP 500 (the blocked-component
IOException is not mapped to 400) — track as a usability/status-code fix.
|
Test 21: POST /unpack/all/config with per-request config
curl -s -X POST -F "file=@test_recursive_embedded.docx" \
-F 'config={"pdf-parser":{"ocr":{"strategy":"NO_OCR"}}}' \
http://localhost:9998/unpack/all/config -o /tmp/unpack-config.zip
unzip -l /tmp/unpack-config.zip
Expected: ZIP with extracted embedded files (config applied). Note there is no
/unpack/config path — the config-variant of unpack is /unpack/all/config.
Server Options
Test 23: Custom Port
java -jar tika-server-standard-4.0.0-SNAPSHOT.jar --port 9999 &
sleep 8
curl -s http://localhost:9999/version
Expected: Server responds on port 9999.
Headers
Test 26: Removed X-Tika-* headers are ignored
The X-Tika-OCR* and X-Tika-PDF* header families no longer exist — grep X-Tika
over tika-server/ finds nothing. This test only confirms that sending one is inert
rather than an error; it does not change OCR behaviour.
curl -s -X PUT -H "X-Tika-OCRskipOcr: true" -T testPDF.pdf http://localhost:9998/tika/text
Expected: HTTP 200 with the same body as the same request without the header. To
configure OCR in 4.x, use tika-config.json (or per-request config where enabled) —
see Migrating tika-server to 4.x.
Usability Test Results
The following endpoints were tested and verified working:
Default Mode (allowPipes=false, allowPerRequestConfig=false)
| Endpoint | Method | Status |
|---|---|---|
|
GET |
PASS |
|
PUT |
PASS |
|
PUT |
PASS |
|
PUT |
PASS |
|
PUT |
PASS |
|
PUT |
PASS |
|
PUT |
PASS |
|
PUT |
PASS |
|
PUT |
PASS |
|
PUT |
PASS |
|
PUT |
PASS |
|
PUT |
PASS |
|
PUT |
PASS |
|
GET |
PASS |
|
GET |
PASS |
|
GET |
PASS |
|
POST |
PASS |
|
POST |
PASS |
|
POST |
BLOCKED (403) - Expected |
|
POST |
BLOCKED (403) - Expected |
|
POST |
BLOCKED (403) - Expected |
|
POST |
BLOCKED (403) - Expected |
Quick Reference
Basic Parsing
# Text output
curl -X PUT -T file.pdf http://localhost:9998/tika/text
# HTML output
curl -X PUT -T file.pdf http://localhost:9998/tika/html
# JSON output (metadata + content)
curl -X PUT -T file.pdf http://localhost:9998/tika/json
Implementation Notes
Automatic Component Configuration
The server automatically configures the required fetcher and emitter for pipes-based parsing:
-
_\_tika-server: A file-system-fetcher with
basePathpointing to a dedicated temp directory for input files. It is the over-threshold path for uploads to/tika,/rmeta,/meta,/detectand/unpack: a body at or belowmaxInlineBytesis carried inside the request and served by the built-in\_\_bytesfetcher instead, so it never reaches this directory. -
\_\_unpack: A file-system-emitter with
basePathpointing to a dedicated temp directory for unpacked files. This is only created when the/unpackendpoint is enabled (default). This enables the/unpack/allendpoint to return embedded files as a ZIP.
Both temp directories are cleaned up on server shutdown.
The _\_ prefix is reserved. Component ids beginning with _\_ name components the server wires up for itself: a /pipes or /async request that names one is rejected, a config file that defines one fails at startup, and they are omitted from the fetcher and emitter lists reported in error messages. Ids you configure yourself may contain only letters, digits, ., _ and -, and are trimmed of surrounding whitespace when loaded.
If a user config file does not include plugin-roots, the server automatically adds a default value: a plugins directory beside the server jar if one exists, otherwise plugins in the current working directory. An explicit plugin-roots in the user config is never overwritten.