From eda0ad271ef331c1ac3d50549d2e5c788dc66b4f Mon Sep 17 00:00:00 2001 From: Bert Bos Date: Wed, 22 Apr 2026 20:59:14 +0200 Subject: [PATCH 1/4] Do not silently accept requests for subdirectories MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Terms in the vocabulary cannot contain slashes and therefore a request for the term ‘foo/bar’ (i.e., https://www.w3.org/ns/sosa/foo/bar) now returns 404, while a request for ‘foo’ (i.e., https://www.w3.org/ns/sosa/foo) returns sosa.ttl or https://www.w3.org/TR/vocab-ssn/#SOSAfoo as before. This should reduce the number of requests that return 200 instead of 404 and make the address space still infinite, but a little less, as asked for in issue #12. --- sosa/.htaccess | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sosa/.htaccess b/sosa/.htaccess index f079425c..a87e217e 100644 --- a/sosa/.htaccess +++ b/sosa/.htaccess @@ -92,7 +92,7 @@ RewriteRule ^$ sosa?term= [N] ###################################################################### RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{QUERY_STRING} ="" -RewriteRule ^(.*)$ sosa?term=$1 [N] +RewriteRule ^([^/]*)$ sosa?term=$1 [N] ###################################################################### # Request for /ns/sosa/sosa.html?term=foo where foo is not empty. From 01d2a882000e10b6d7a45513142a589985509b1f Mon Sep 17 00:00:00 2001 From: Bert Bos Date: Wed, 22 Apr 2026 21:02:00 +0200 Subject: [PATCH 2/4] Do not silently accept requests for subdirectories MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Terms in the vocabulary cannot contain slashes and therefore a request for the term ‘foo/bar’ (i.e., https://www.w3.org/ns/ssn/foo/bar) now returns 404, while a request for ‘foo’ (i.e., https://www.w3.org/ns/sosa/foo) returns ssn.ttl or https://www.w3.org/TR/vocab-ssn/#SSNfoo as before. This should reduce the number of requests that return 200 instead of 404 and make the address space still infinite, but a little less, as asked for in https://github.com/w3c/ns/issues/12 --- ssn/.htaccess | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ssn/.htaccess b/ssn/.htaccess index 76c0b0b3..f77e82f8 100644 --- a/ssn/.htaccess +++ b/ssn/.htaccess @@ -73,7 +73,7 @@ RewriteRule ^$ ssn?term= [N] ###################################################################### RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{QUERY_STRING} ="" -RewriteRule ^(.*)$ ssn?term=$1 [N] +RewriteRule ^([^/]*)$ ssn?term=$1 [N] ###################################################################### # Request for ssn.html?term=foo where foo is not empty. Return From 4b645c03e478f7d6fe035bf9224fb545a9b751bf Mon Sep 17 00:00:00 2001 From: Bert Bos Date: Wed, 22 Apr 2026 21:36:30 +0200 Subject: [PATCH 3/4] A request for x/y should now return 404 Also fix some content types: The server returns charset=utf-8 also for text/turtle --- ssn/regression-tests.sh | 78 ++++++++++++++++++++--------------------- 1 file changed, 39 insertions(+), 39 deletions(-) diff --git a/ssn/regression-tests.sh b/ssn/regression-tests.sh index b84701ef..d4effdb4 100755 --- a/ssn/regression-tests.sh +++ b/ssn/regression-tests.sh @@ -18,48 +18,48 @@ base="https://www.w3.org/ns/ssn" # 5. expected final URL (only used if response = 200) # tests=( - 0 'text/html,*/*;q=0.8' '' 200 'text/html; charset=utf-8' 'https://www.w3.org/TR/vocab-ssn/' - 1 'text/html,*/*;q=0.8' '/' 200 'text/html; charset=utf-8' 'https://www.w3.org/TR/vocab-ssn/' - 2 'text/html,*/*;q=0.8' '/ssn' 200 'text/html; charset=utf-8' 'https://www.w3.org/TR/vocab-ssn/' - 3 'text/html,*/*;q=0.8' '/ssn.html' 200 'text/html; charset=utf-8' 'https://www.w3.org/TR/vocab-ssn/' - 4 'text/html,*/*;q=0.8' '/ssn.ttl' 200 'text/turtle' "$base/ssn.ttl" - 5 'text/html,*/*;q=0.8' '/dul' 200 'text/turtle' "$base/dul" - 6 'text/html,*/*;q=0.8' '/System' 200 'text/html; charset=utf-8' 'https://www.w3.org/TR/vocab-ssn/#SSNSystem' + 0 'text/html,*/*;q=0.8' '' 200 'text/html; charset=utf-8' 'https://www.w3.org/TR/vocab-ssn/' + 1 'text/html,*/*;q=0.8' '/' 200 'text/html; charset=utf-8' 'https://www.w3.org/TR/vocab-ssn/' + 2 'text/html,*/*;q=0.8' '/ssn' 200 'text/html; charset=utf-8' 'https://www.w3.org/TR/vocab-ssn/' + 3 'text/html,*/*;q=0.8' '/ssn.html' 200 'text/html; charset=utf-8' 'https://www.w3.org/TR/vocab-ssn/' + 4 'text/html,*/*;q=0.8' '/ssn.ttl' 200 'text/turtle; charset=utf-8' "$base/ssn.ttl" + 5 'text/html,*/*;q=0.8' '/dul' 200 'text/turtle; charset=utf-8' "$base/dul" + 6 'text/html,*/*;q=0.8' '/System' 200 'text/html; charset=utf-8' 'https://www.w3.org/TR/vocab-ssn/#SSNSystem' - 8 'text/html,*/*;q=0.8' '/ssn?query' 200 'text/html; charset=utf-8' 'https://www.w3.org/TR/vocab-ssn/' - 9 'text/html,*/*;q=0.8' '/x?y' 200 'text/html; charset=utf-8' 'https://www.w3.org/TR/vocab-ssn/#SSNx' - 10 'text/html,*/*;q=0.8' '/x/y' 200 'text/html; charset=utf-8' 'https://www.w3.org/TR/vocab-ssn/#SSNx/y' - 11 'text/html,*/*;q=0.8' '/?foo' 200 'text/html; charset=utf-8' 'https://www.w3.org/TR/vocab-ssn/' - 12 'text/html' '' 200 'text/html; charset=utf-8' 'https://www.w3.org/TR/vocab-ssn/' - 13 'text/html' '/' 200 'text/html; charset=utf-8' 'https://www.w3.org/TR/vocab-ssn/' - 14 'text/html' '/ssn' 200 'text/html; charset=utf-8' 'https://www.w3.org/TR/vocab-ssn/' - 15 'text/html' '/ssn.html' 200 'text/html; charset=utf-8' 'https://www.w3.org/TR/vocab-ssn/' - 16 'text/html' '/ssn.ttl' 200 'text/turtle' "$base/ssn.ttl" - 17 'text/html' '/dul' 406 '-' '-' - 18 'text/html' '/System' 200 'text/html; charset=utf-8' 'https://www.w3.org/TR/vocab-ssn/#SSNSystem' + 8 'text/html,*/*;q=0.8' '/ssn?query' 200 'text/html; charset=utf-8' 'https://www.w3.org/TR/vocab-ssn/' + 9 'text/html,*/*;q=0.8' '/x?y' 200 'text/html; charset=utf-8' 'https://www.w3.org/TR/vocab-ssn/#SSNx' + 10 'text/html,*/*;q=0.8' '/x/y' 200 'text/html; charset=utf-8' 'https://www.w3.org/TR/vocab-ssn/#SSNx/y' + 11 'text/html,*/*;q=0.8' '/?foo' 200 'text/html; charset=utf-8' 'https://www.w3.org/TR/vocab-ssn/' + 12 'text/html' '' 200 'text/html; charset=utf-8' 'https://www.w3.org/TR/vocab-ssn/' + 13 'text/html' '/' 200 'text/html; charset=utf-8' 'https://www.w3.org/TR/vocab-ssn/' + 14 'text/html' '/ssn' 200 'text/html; charset=utf-8' 'https://www.w3.org/TR/vocab-ssn/' + 15 'text/html' '/ssn.html' 200 'text/html; charset=utf-8' 'https://www.w3.org/TR/vocab-ssn/' + 16 'text/html' '/ssn.ttl' 200 'text/turtle; charset=utf-8' "$base/ssn.ttl" + 17 'text/html' '/dul' 406 '-' '-' + 18 'text/html' '/System' 200 'text/html; charset=utf-8' 'https://www.w3.org/TR/vocab-ssn/#SSNSystem' - 20 'text/html' '/ssn?query' 200 'text/html; charset=utf-8' 'https://www.w3.org/TR/vocab-ssn/' - 21 'text/html' '/x?y' 200 'text/html; charset=utf-8' 'https://www.w3.org/TR/vocab-ssn/#SSNx' - 22 'text/html' '/x/y' 200 'text/html; charset=utf-8' 'https://www.w3.org/TR/vocab-ssn/#SSNx/y' - 23 'text/html' '/?foo' 200 'text/html; charset=utf-8' 'https://www.w3.org/TR/vocab-ssn/' - 24 '' '' 200 'text/turtle' "$base/" - 25 '' '/' 200 'text/turtle' "$base/" - 26 '' '/ssn' 200 'text/turtle' "$base/ssn" - 27 '' '/ssn.html' 200 'text/html; charset=utf-8' 'https://www.w3.org/TR/vocab-ssn/' - 28 '' '/ssn.ttl' 200 'text/turtle' "$base/ssn.ttl" - 29 '' '/dul' 200 'text/turtle' "$base/dul" - 30 '' '/System' 200 'text/turtle' "$base/System" + 20 'text/html' '/ssn?query' 200 'text/html; charset=utf-8' 'https://www.w3.org/TR/vocab-ssn/' + 21 'text/html' '/x?y' 200 'text/html; charset=utf-8' 'https://www.w3.org/TR/vocab-ssn/#SSNx' + 22 'text/html' '/x/y' 200 'text/html; charset=utf-8' 'https://www.w3.org/TR/vocab-ssn/#SSNx/y' + 23 'text/html' '/?foo' 200 'text/html; charset=utf-8' 'https://www.w3.org/TR/vocab-ssn/' + 24 '' '' 200 'text/turtle; charset=utf-8' "$base/" + 25 '' '/' 200 'text/turtle; charset=utf-8' "$base/" + 26 '' '/ssn' 200 'text/turtle; charset=utf-8' "$base/ssn" + 27 '' '/ssn.html' 200 'text/html; charset=utf-8' 'https://www.w3.org/TR/vocab-ssn/' + 28 '' '/ssn.ttl' 200 'text/turtle; charset=utf-8' "$base/ssn.ttl" + 29 '' '/dul' 200 'text/turtle; charset=utf-8' "$base/dul" + 30 '' '/System' 200 'text/turtle; charset=utf-8' "$base/System" - 32 '' '/ssn?query' 200 'text/turtle' "$base/ssn?query" - 33 '' '/x?y' 200 'text/turtle' "$base/x?y" - 34 '' '/x/y' 200 'text/turtle' "$base/x/y" - 35 '' '/?foo' 200 'text/turtle' "$base/?foo" - 36 'text/html,text/turtle' '/' 200 'text/turtle' "$base/" - 37 'application/rdf+xml' '/' 200 'application/rdf+xml' "$base/" - 38 'text/turtle' '/hosts' 200 'text/turtle' "$base/hosts" - 39 '*/*' '/' 200 'text/turtle' "$base/" - 40 'text/html,*/*;qs=0.8' '/x?term=y' 404 '-' '-' - 41 'text/turtle,text/html;qs=0.1' '/' 200 'text/turtle' "$base/" + 32 '' '/ssn?query' 200 'text/turtle; charset=utf-8' "$base/ssn?query" + 33 '' '/x?y' 200 'text/turtle; charset=utf-8' "$base/x?y" + 34 '' '/x/y' 200 '-' '-' + 35 '' '/?foo' 200 'text/turtle; charset=utf-8' "$base/?foo" + 36 'text/html,text/turtle' '/' 200 'text/turtle; charset=utf-8' "$base/" + 37 'application/rdf+xml' '/' 200 'application/rdf+xml; qs=0.9' "$base/" + 38 'text/turtle' '/hosts' 200 'text/turtle; charset=utf-8' "$base/hosts" + 39 '*/*' '/' 200 'text/turtle; charset=utf-8' "$base/" + 40 'text/html,*/*;qs=0.8' '/x?term=y' 404 '-' '-' + 41 'text/turtle,text/html;qs=0.1' '/' 200 'text/turtle; charset=utf-8' "$base/" ) for ((i = 0; 6 * i < ${#tests[@]}; i++)); do From 89a0f2c20cff7ac8ef7ebb316461c6176b22b950 Mon Sep 17 00:00:00 2001 From: Bert Bos Date: Wed, 22 Apr 2026 21:36:53 +0200 Subject: [PATCH 4/4] A request for x/y should now return 404 Also fix some content types: The server returns charset=utf-8 also for text/turtle --- sosa/regression-tests.sh | 80 ++++++++++++++++++++-------------------- 1 file changed, 40 insertions(+), 40 deletions(-) diff --git a/sosa/regression-tests.sh b/sosa/regression-tests.sh index d56103c1..11c4b82e 100755 --- a/sosa/regression-tests.sh +++ b/sosa/regression-tests.sh @@ -18,48 +18,48 @@ base="https://www.w3.org/ns/sosa" # 5. expected final URL (only used if response = 200) # tests=( - 0 'text/html,*/*;q=0.8' '' 200 'text/html; charset=utf-8' 'https://www.w3.org/TR/vocab-ssn/' - 1 'text/html,*/*;q=0.8' '/' 200 'text/html; charset=utf-8' 'https://www.w3.org/TR/vocab-ssn/' - 2 'text/html,*/*;q=0.8' '/sosa' 200 'text/html; charset=utf-8' 'https://www.w3.org/TR/vocab-ssn/' - 3 'text/html,*/*;q=0.8' '/sosa.html' 200 'text/html; charset=utf-8' 'https://www.w3.org/TR/vocab-ssn/' - 4 'text/html,*/*;q=0.8' '/sosa.ttl' 200 'text/turtle' "$base/sosa.ttl" - 5 'text/html,*/*;q=0.8' '/om' 200 'text/turtle' "$base/om" - 6 'text/html,*/*;q=0.8' '/Actuation' 200 'text/html; charset=utf-8' 'https://www.w3.org/TR/vocab-ssn/#SOSAActuation' + 0 'text/html,*/*;q=0.8' '' 200 'text/html; charset=utf-8' 'https://www.w3.org/TR/vocab-ssn/' + 1 'text/html,*/*;q=0.8' '/' 200 'text/html; charset=utf-8' 'https://www.w3.org/TR/vocab-ssn/' + 2 'text/html,*/*;q=0.8' '/sosa' 200 'text/html; charset=utf-8' 'https://www.w3.org/TR/vocab-ssn/' + 3 'text/html,*/*;q=0.8' '/sosa.html' 200 'text/html; charset=utf-8' 'https://www.w3.org/TR/vocab-ssn/' + 4 'text/html,*/*;q=0.8' '/sosa.ttl' 200 'text/turtle; charset=utf-8' "$base/sosa.ttl" + 5 'text/html,*/*;q=0.8' '/om' 200 'text/turtle; charset=utf-8' "$base/om" + 6 'text/html,*/*;q=0.8' '/Actuation' 200 'text/html; charset=utf-8' 'https://www.w3.org/TR/vocab-ssn/#SOSAActuation' - 8 'text/html,*/*;q=0.8' '/sosa?query' 200 'text/html; charset=utf-8' 'https://www.w3.org/TR/vocab-ssn/' - 9 'text/html,*/*;q=0.8' '/x?y' 200 'text/html; charset=utf-8' 'https://www.w3.org/TR/vocab-ssn/#SOSAx' - 10 'text/html,*/*;q=0.8' '/x/y' 200 'text/html; charset=utf-8' 'https://www.w3.org/TR/vocab-ssn/#SOSAx/y' - 11 'text/html,*/*;q=0.8' '/?foo' 200 'text/html; charset=utf-8' 'https://www.w3.org/TR/vocab-ssn/' - 12 'text/html' '' 200 'text/html; charset=utf-8' 'https://www.w3.org/TR/vocab-ssn/' - 13 'text/html' '/' 200 'text/html; charset=utf-8' 'https://www.w3.org/TR/vocab-ssn/' - 14 'text/html' '/sosa' 200 'text/html; charset=utf-8' 'https://www.w3.org/TR/vocab-ssn/' - 15 'text/html' '/sosa.html' 200 'text/html; charset=utf-8' 'https://www.w3.org/TR/vocab-ssn/' - 16 'text/html' '/sosa.ttl' 200 'text/turtle' "$base/sosa.ttl" - 17 'text/html' '/om' 406 '-' '-' - 18 'text/html' '/Actuation' 200 'text/html; charset=utf-8' 'https://www.w3.org/TR/vocab-ssn/#SOSAActuation' + 8 'text/html,*/*;q=0.8' '/sosa?query' 200 'text/html; charset=utf-8' 'https://www.w3.org/TR/vocab-ssn/' + 9 'text/html,*/*;q=0.8' '/x?y' 200 'text/html; charset=utf-8' 'https://www.w3.org/TR/vocab-ssn/#SOSAx' + 10 'text/html,*/*;q=0.8' '/x/y' 200 'text/html; charset=utf-8' 'https://www.w3.org/TR/vocab-ssn/#SOSAx/y' + 11 'text/html,*/*;q=0.8' '/?foo' 200 'text/html; charset=utf-8' 'https://www.w3.org/TR/vocab-ssn/' + 12 'text/html' '' 200 'text/html; charset=utf-8' 'https://www.w3.org/TR/vocab-ssn/' + 13 'text/html' '/' 200 'text/html; charset=utf-8' 'https://www.w3.org/TR/vocab-ssn/' + 14 'text/html' '/sosa' 200 'text/html; charset=utf-8' 'https://www.w3.org/TR/vocab-ssn/' + 15 'text/html' '/sosa.html' 200 'text/html; charset=utf-8' 'https://www.w3.org/TR/vocab-ssn/' + 16 'text/html' '/sosa.ttl' 200 'text/turtle; charset=utf-8' "$base/sosa.ttl" + 17 'text/html' '/om' 406 '-' '-' + 18 'text/html' '/Actuation' 200 'text/html; charset=utf-8' 'https://www.w3.org/TR/vocab-ssn/#SOSAActuation' - 20 'text/html' '/sosa?query' 200 'text/html; charset=utf-8' 'https://www.w3.org/TR/vocab-ssn/' - 21 'text/html' '/x?y' 200 'text/html; charset=utf-8' 'https://www.w3.org/TR/vocab-ssn/#SOSAx' - 22 'text/html' '/x/y' 200 'text/html; charset=utf-8' 'https://www.w3.org/TR/vocab-ssn/#SOSAx/y' - 23 'text/html' '/?foo' 200 'text/html; charset=utf-8' 'https://www.w3.org/TR/vocab-ssn/' - 24 '' '' 200 'text/turtle' "$base/" - 25 '' '/' 200 'text/turtle' "$base/" - 26 '' '/sosa' 200 'text/turtle' "$base/sosa" - 27 '' '/sosa.html' 200 'text/html; charset=utf-8' 'https://www.w3.org/TR/vocab-ssn/' - 28 '' '/sosa.ttl' 200 'text/turtle' "$base/sosa.ttl" - 29 '' '/om' 200 'text/turtle' "$base/om" - 30 '' '/Actuation' 200 'text/turtle' "$base/Actuation" - 31 '' '/prov' 200 'text/turtle' "$base/prov/" - 32 '' '/sosa?query' 200 'text/turtle' "$base/sosa?query" - 33 '' '/x?y' 200 'text/turtle' "$base/x?y" - 34 '' '/x/y' 200 'text/turtle' "$base/x/y" - 35 '' '/?foo' 200 'text/turtle' "$base/?foo" - 36 'text/html,text/turtle' '/' 200 'text/turtle' "$base/" - 37 'application/rdf+xml' '/' 200 'application/rdf+xml' "$base/" - 38 'text/turtle' '/hosts' 200 'text/turtle' "$base/hosts" - 39 '*/*' '/' 200 'text/turtle' "$base/" - 40 'text/html,*/*;qs=0.8' '/x?term=y' 404 '-' '-' - 41 'text/turtle,text/html;qs=0.1' '/' 200 'text/turtle' "$base/" + 20 'text/html' '/sosa?query' 200 'text/html; charset=utf-8' 'https://www.w3.org/TR/vocab-ssn/' + 21 'text/html' '/x?y' 200 'text/html; charset=utf-8' 'https://www.w3.org/TR/vocab-ssn/#SOSAx' + 22 'text/html' '/x/y' 200 'text/html; charset=utf-8' 'https://www.w3.org/TR/vocab-ssn/#SOSAx/y' + 23 'text/html' '/?foo' 200 'text/html; charset=utf-8' 'https://www.w3.org/TR/vocab-ssn/' + 24 '' '' 200 'text/turtle; charset=utf-8' "$base/" + 25 '' '/' 200 'text/turtle; charset=utf-8' "$base/" + 26 '' '/sosa' 200 'text/turtle; charset=utf-8' "$base/sosa" + 27 '' '/sosa.html' 200 'text/html; charset=utf-8' 'https://www.w3.org/TR/vocab-ssn/' + 28 '' '/sosa.ttl' 200 'text/turtle; charset=utf-8' "$base/sosa.ttl" + 29 '' '/om' 200 'text/turtle; charset=utf-8' "$base/om" + 30 '' '/Actuation' 200 'text/turtle; charset=utf-8' "$base/Actuation" + 31 '' '/prov' 200 'text/turtle; charset=utf-8' "$base/prov/" + 32 '' '/sosa?query' 200 'text/turtle; charset=utf-8' "$base/sosa?query" + 33 '' '/x?y' 200 'text/turtle; charset=utf-8' "$base/x?y" + 34 '' '/x/y' 404 '-' '-' + 35 '' '/?foo' 200 'text/turtle; charset=utf-8' "$base/?foo" + 36 'text/html,text/turtle' '/' 200 'text/turtle; charset=utf-8' "$base/" + 37 'application/rdf+xml' '/' 200 'application/rdf+xml; qs=0.9' "$base/" + 38 'text/turtle' '/hosts' 200 'text/turtle; charset=utf-8' "$base/hosts" + 39 '*/*' '/' 200 'text/turtle; charset=utf-8' "$base/" + 40 'text/html,*/*;qs=0.8' '/x?term=y' 404 '-' '-' + 41 'text/turtle,text/html;qs=0.1' '/' 200 'text/turtle; charset=utf-8' "$base/" ) for ((i = 0; 6 * i < ${#tests[@]}; i++)); do