Task #8865

Configure web server to redirect DataONE dataset PIRIs

Added by Bryce Mecum over 3 years ago. Updated about 3 years ago.

Target version:
Start date:
Due date:
% Done:


Product Version:
Story Points:


As scoped out in, we'd like to be able to referenced DataONE resources in a linked-open-data manner. This is useful because it forms the basis of building more interested things on top of them. However, those resources (e.g., Data Packages) don't currently have, subjectively, suitable IRIs, though they have a variety of URLs.

The ideas in the above proposal are multi-tiered but a good first start can be achieved immediately: Support a PIRI space for "Datasets" (DataONE Data Packages) by redirecting requests from their IRI form:$ID

to their URL form:$ID.

Such a redirection can be achieved within our Apache configuration using mod_rewrite and a rule similar to:

RewriteRule  "^/datasets/(.+)$" "$1" [L,R]


#1 Updated by Bryce Mecum about 3 years ago

Talked with Dave V and Chris J a few weeks ago and they indicated they wanted to review the Apache config on before proceeding. Waiting on that now.

#2 Updated by Bryce Mecum about 3 years ago

I took a look at the config myself and I see no conflicts we can't work around but I do see why caution was warranted. Since launching the website redesign, we put in a few wildcard redirects to keep the old website up ( and all links resolving as well as keep our Drupal instance available.

The relevant part of the config has rewrites in for three purposes:

  1. Enabling access to Drupal

    ProxyPassMatch ^/(.*\.php(/.*)?)$ "fcgi://"

    This doesn't conflict with the proposed config because /foo.php doesn't overlap with /datasets/xyz.

  2. Forcing a www subdomain for the main site (i.e., 301 requests like to

    RewriteEngine On
    RewriteCond %{HTTP_HOST} !^www\. [NC]
    RewriteCond %{REMOTE_ADDR} !^127\.0\.0\.1
    RewriteRule ^(.*)$ https://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

    This would conflict because our PIRI space is$X so our PIRI redirect needs to be above this.

  3. Handle links for the old site:

    RewriteCond /var/www/{REQUEST_URI} !-f
    RewriteCond /var/www/{REQUEST_URI} !-d
    RewriteRule ^(.*)${REQUEST_URI} [L]

    This would conflict too, but we already have to have the PIRI redirect above (2) so this is fine to keep where it is.

So my take on this is that we can put my proposed rule in before or after (1) and we'll be good.

#3 Updated by Dave Vieglais about 3 years ago

Assessment looks good to me.

#4 Updated by Chris Jones about 3 years ago

This looks great Bryce, thanks for closely evaluating the rewrite rules. Matt had mentioned that we may want to transition away from and primarily use So I think (2) above could probably change such that all links to get redirected to, which also shouldn't affect your addition.

#5 Updated by Bryce Mecum about 3 years ago

Sounds like a great change to me.

#6 Updated by Bryce Mecum about 3 years ago

After testing locally, I went to make this change on Things did not go as planned.

Best I can tell, it turns out that Apache and/or mod_rewrite can't stay away from mangling (encoding/decoding) URLs. I wasn't able to find a combination of directives or mod_rewrite flags that'll simply take exactly what comes after "/datasets/" and redirect to it over on

The types of encoded identifiers that cause issues are our doi:10.1234/ABCD and http(s):// identifiers. This is partly to do with having urlencodeable characters but it appears more to do with having slashes in the identifier and encoded slashes in the canonical URL.

The nearest config I got to working was:

AllowEncodedSlashes NoDecode
AcceptPathInfo      On
RewriteRule ^/datasets/(.+)$ "$1" [L,R,NE,B=:]

NE stops mod_rewrite from re-encoding characters we've already encoded and I came up with B=: because Apache or mod_rewrite can't not decode %3A (:) so we have to re-encode it.

The Holy Grail identifier to test this approach with is which has a canonical URI of Under the above config, this redirect just hard 404s and I have no idea why.

I'm going to continue looking at this tomorrow but if anyone has any hot tips or wants to take a look with me please let me know.

#7 Updated by Bryce Mecum about 3 years ago

I had some time to look at this more closely but haven't come up with a totally satisfying solution. I think I have one though, so read on. Ideally, whatever string of characters is in the path portion of the just simply comes out of Apache unmodified so the downstream client can do what it needs to. Unfortunately, Apache prefers to decode URLs and mod_rewrite appears to get that decoded data and not the raw data. The downstream application does get the raw data but mod_rewrite does ont.

For an example of what I mean by modifying: If we just use a simple RewriteRule, Apache does this for even a relatively easy identifier:

urn%3Auuid%3Ac6feebc4-d822-49a2-860d-32bd808e02f3 -> urn:uuid:c6feebc4-d822-49a2-860d-32bd808e02f3

And what we want is the original input, not the decoded form. I'll note, though:

URI producing applications should percent-encode data octets that
correspond to characters in the reserved set unless these characters
are specifically allowed by the URI scheme to represent data in that
component. --

The above implies that : (a reserved character), when in the path part of a URI, doesn't need to be encoded because it doesn't conflict with the interpretation of the URI. So I think technically this is "fine". Just not perfect.

mod_rewrite has a number of flags that I think are relevant here

  • [NE] noescape: "By default, special characters, such as & and ?, for example, will be converted to their hexcode equivalent. Using the [NE] flag prevents that from happening."
  • [B] escape backreferences: "escape non-alphanumeric characters before applying the transformation."
  • [BNP] backrefnoplus (Don't escape space to +)

Note: [NE] doesn't just apply to & and ? but also to % which means we need it on to not re-encode already-percent-encoded chars.

To get a sense of what the options actually look like, I wrote a script to test a few fake and a few real identifiers that exercise our identifier space pretty well. Below is a set of results for various combinations of flags. For each pair of lines, the first line is the input and the second line is the result after Apache + mod_rewrite have had at it.

Note: [L,R] aren't related to encoding but are included for completeness.




























Of all of these, [L,R,NE] looks like the way to go. This is mainly because, while it doesn't stop Apache from mucking with the URL, the result looks equivalent according to the spec and MetacatUI, for example, can handle it. As an example, under this rule, turns into which contains a mix of encoded things and things we'd normally encode such as the ?. That said, when decoded, the result is correct:

I'd love a few sets of eyes on this but I'll make a note to come around to it before too long so we can get this done.

#8 Updated by Bryce Mecum about 3 years ago

  • % Done changed from 0 to 100
  • Status changed from New to Closed

Added the following to

# 20201014 mecum
# Enables Dataone /datasets PURI space
# Ref:
AllowEncodedSlashes NoDecode
RewriteRule ^/datasets/(.+)$$1 [L,NE,R]

I think this is good enough for now and also as good as we're going to get with a pure-Apache approach.

Also available in: Atom PDF

Add picture from clipboard (Maximum size: 14.8 MB)