This is an automated email from the ASF dual-hosted git repository.
tballison 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 f28c1e7d25 TIKA-4977: detect *.rs as text/x-rust; RLS services XML by
root element (#3365)
f28c1e7d25 is described below
commit f28c1e7d25fe7d6f41ea2db65974bc8b41c96521
Author: Tim Allison <[email protected]>
AuthorDate: Mon Oct 19 14:30:35 2026 +0100
TIKA-4977: detect *.rs as text/x-rust; RLS services XML by root element
(#3365)
---
CHANGES.txt | 4 ++++
.../org/apache/tika/mime/tika-mimetypes.xml | 9 ++++++-
.../java/org/apache/tika/TikaDetectionTest.java | 3 ++-
.../org/apache/tika/mime/MimeDetectionTest.java | 28 ++++++++++++++++++++++
4 files changed, 42 insertions(+), 2 deletions(-)
diff --git a/CHANGES.txt b/CHANGES.txt
index 1c02d2fd92..4b04bc03bc 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,5 +1,9 @@
Release 4.2.0 - unreleased
+ * Files named *.rs are now detected as text/x-rust (Rust source) instead of
+ application/rls-services+xml. RLS services XML is still detected from its
+ root element, whatever the file name (TIKA-4977).
+
* Opt-in "metadata-list": {"typedValues": true} writes INTEGER, REAL and
BOOLEAN metadata as JSON numbers and booleans, and tk:chunks as nested
JSON rather than an escaped string, in -J, /rmeta and the JSON emitters.
diff --git
a/tika-core/src/main/resources/org/apache/tika/mime/tika-mimetypes.xml
b/tika-core/src/main/resources/org/apache/tika/mime/tika-mimetypes.xml
index 88387956e5..7fa05d2920 100644
--- a/tika-core/src/main/resources/org/apache/tika/mime/tika-mimetypes.xml
+++ b/tika-core/src/main/resources/org/apache/tika/mime/tika-mimetypes.xml
@@ -1040,7 +1040,8 @@
<mime-type type="application/riscos"/>
<mime-type type="application/rlmi+xml"/>
<mime-type type="application/rls-services+xml">
- <glob pattern="*.rs"/>
+ <root-XML namespaceURI="urn:ietf:params:xml:ns:rls-services"
localName="rls-services"/>
+ <!-- <glob pattern="*.rs"/> - conflicts with text/x-rust -->
</mime-type>
<mime-type type="application/rsd+xml">
<glob pattern="*.rsd"/>
@@ -8578,6 +8579,12 @@
<sub-class-of type="text/plain"/>
</mime-type>
+ <mime-type type="text/x-rust">
+ <_comment>Rust source code</_comment>
+ <glob pattern="*.rs"/>
+ <sub-class-of type="text/plain"/>
+ </mime-type>
+
<mime-type type="text/x-scala">
<_comment>Scala source code</_comment>
<glob pattern="*.scala"/>
diff --git a/tika-core/src/test/java/org/apache/tika/TikaDetectionTest.java
b/tika-core/src/test/java/org/apache/tika/TikaDetectionTest.java
index 8dead957bf..77fe46899a 100644
--- a/tika-core/src/test/java/org/apache/tika/TikaDetectionTest.java
+++ b/tika-core/src/test/java/org/apache/tika/TikaDetectionTest.java
@@ -121,7 +121,8 @@ public class TikaDetectionTest {
assertEquals("application/relax-ng-compact-syntax",
tika.detect("x.rnc"));
assertEquals("application/resource-lists+xml", tika.detect("x.rl"));
assertEquals("application/resource-lists-diff+xml",
tika.detect("x.rld"));
- assertEquals("application/rls-services+xml", tika.detect("x.rs"));
+ // httpd maps .rs to application/rls-services+xml; Rust source wins
(TIKA-4977)
+ assertEquals("text/x-rust", tika.detect("x.rs"));
assertEquals("application/rsd+xml", tika.detect("x.rsd"));
assertEquals("application/rss+xml", tika.detect("x.rss"));
assertEquals("application/rtf", tika.detect("x.rtf"));
diff --git
a/tika-core/src/test/java/org/apache/tika/mime/MimeDetectionTest.java
b/tika-core/src/test/java/org/apache/tika/mime/MimeDetectionTest.java
index 01dab1f671..3d7f214169 100644
--- a/tika-core/src/test/java/org/apache/tika/mime/MimeDetectionTest.java
+++ b/tika-core/src/test/java/org/apache/tika/mime/MimeDetectionTest.java
@@ -214,6 +214,34 @@ public class MimeDetectionTest {
}
}
+ private static MediaType detect(byte[] bytes, String name) throws
IOException {
+ Metadata metadata = new Metadata();
+ if (name != null) {
+ metadata.set(TikaCoreProperties.RESOURCE_NAME_KEY, name);
+ }
+ try (TikaInputStream tis = TikaInputStream.get(bytes)) {
+ return MIME_TYPES.detect(tis, metadata, new ParseContext());
+ }
+ }
+
+ @Test
+ public void testRustVersusRlsServices() throws IOException {
+ MediaType rust = MediaType.text("x-rust");
+ MediaType rls = MediaType.application("rls-services+xml");
+ assertEquals(rust, detect("fn main() {}\n".getBytes(UTF_8),
"main.rs"));
+ assertEquals(rust, detect("// Licensed to the ASF\nfn main()
{}\n".getBytes(UTF_8),
+ "main.rs"));
+
+ byte[] rlsXml = ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ + "<rls-services
xmlns=\"urn:ietf:params:xml:ns:rls-services\">"
+ + "<service
uri=\"sip:[email protected]\"/></rls-services>").getBytes(UTF_8);
+ assertEquals(rls, detect(rlsXml, "services.rs"));
+ assertEquals(rls, detect(rlsXml, null));
+
+ byte[] png = {(byte) 0x89, 'P', 'N', 'G', '\r', '\n', 0x1a, '\n', 0,
0, 0, 0};
+ assertEquals(MediaType.image("png"), detect(png, "main.rs"));
+ }
+
@Test
public void testDetectionWithoutContent() throws IOException {
testUrlWithoutContent("text/html", "test.html");