I’ve searched several SO posts and haven’t found what I’m looking for. It might exists but might be fairly old enough to not show up for me. I found a post (Nginx rewrite: add trailing slash, preserve anchors and query strings) so close to what I need, but it’s regex solution does not work for URL Rewrite for IIS, unless I’m doing it wrong.
Problem
I’m trying to add a forward slash /
to the end of my url paths while also preserving any existing for query strings ?
and anchors #
.
Desired Solution
Basically, here’s the desired results to each problem:
Entry: https://my.site.com/about
Result: https://my.site.com/about/
Entry: https://my.site.com/about?query=string
Result: https://my.site.com/about/?query=string
Entry: https://my.site.com/about#TestAnchor
Result: https://my.site.com/about/#TestAnchor
Entry: https://my.site.com/about?query=string#TestAnchor
Result: https://my.site.com/about/?query=string#TestAnchor
Current Tests
Our current regex ignores query strings and anchors, but I would like to take them into consideration now.
<rule name="AddTrailingSlash" stopProcessing="true">
<match url="^([^.?]+[^.?/])$" />
<action type="Redirect" url="{R:1}/" redirectType="Permanent" />
</rule>
I’ve also tested another regex but it only works if the url contains both a query string AND an anchor.
<rule name="AddTrailingSlash" stopProcessing="true">
<match url="^(.*)(?.*?)(#.*?)$" />
<action type="Redirect" url="{R:1}/{R:2}{R:3}" redirectType="Permanent" />
</rule>
NOTE: I just tested this last one (^(.*)(?.*?)(#.*?)$
) and it actually doesn’t work. If the url already contains a /
before the ?
the test passes which it should not, so I have more work to do here.
Question
Is there a single regex that I can use to solve this or do I need to use multiple rules?
2
Answers
You can try with this regex https://regex101.com/r/6TSqaP/2. This is matching every provided example and solves the problem if the url already has an ending
'/'
.I used your second example as base for my regex, with the following logic.
The parts of the url:
scheme://authority/path?query#fragment
scheme://authority/path
part of the url?query
#fragment
regex explanation
Nginx
Edit: Updated regex to handle dashes (-) and multiple path elements
TL;DR
IIS Rewrite (ALL) URIs with
Trailing Slash
& preserveFragment
andQuery Strings
IIS use ECMAScript so you can Try it here : https://regexr.com/6ele7
Update
IIS Rewrite (Considered) URIs with
Trailing Slash
& preserveFragment
andQuery Strings
Try it here : https://regexr.com/6fk3g
Explaination (All)
Group #1:
^
In first,[^?#]
Any character except?
/#
, Go much but lazy+?
(Stop on first possible, by looking to next)Ignore:
/?
Then if a/
exist or notGroup #2:
[?#]
=?
/#
And.*
Any much character next to that till$
End,(...)?
If existIt work well. But it will deal not right with:
So let’s add an exception…
Name.name.name.ext
as Group #2?(?:...)
Non-Capturing group([^/?#]+.[^/?#]+)?
Look for any possible file name or(?:[?#].*)?
Any possible query or anchor stringsNow everything is OK, except this:
So we need another exception in Group #1
(...|...)
Alternative[^/]+://[^/#?]+
First check if (not lazy) any pattern like...://...
till not/ # ?
exist?Now it work great!
+ Explaination (Considered)
.
&/
character set in first group to just match considered URIs and ignore others?/[^/.?#]+
Check if after last/
the set of characters be not/.?#
Now it is even smaller and faster!
Analyzing other method
As @károly-szabó answered well here, instead of looking for Not-Accepted character sets, we can look for matched pattern.
So if we want to use the method but in simpler way (2 Groups) (+ Some minor optimization), the regex will be:
But URI path Accepted characters are more.
So a wider version of that Regex can be:
Try it here: https://regexr.com/6elea
Note: Still "multibyte Unicode as domain name is allowed" but i ignored that in this method.
P.S.
Actually i don’t think that we should rewrite it on IIS, because of these reasons:
#
can be part of a folder name (by%23
)Ref:
IIS: UrlRewrite middleware query strings are preserved
Google/Anchor tags are stripped from URLs
RFC URI References
URI Wiki
How does IIS URL Rewrite handle # anchor tags
I Mean: