I'm sure this is an easy thing to do but I can't seem to find the answer!

I'm trying to redirect https://carddav.example.com/MYUSERNAME to https://carddav.example.com/remote.php/subdomain/addressbooks/MYUSERNAME/contacts where MYUSERNAME can be anything.

The current RewriteRule I have attempted looks like:

RewriteRule ^/(.*)$ https://carddav.example.com/remote.php/carddav/addressbooks/$1/contacts/ [R=301]
  • Please try something before posting here. If it doesn't work we can help you. This canonical question may be useful to you.
    – John Conde
    Sep 7 '14 at 2:15
  • The closest I've come is this but it doesn't redirect properly RewriteRule ^/(.*)$ https://carddav.example.com/remote.php/carddav/addressbooks/$1/contacts/ [R=301] Sep 7 '14 at 2:34
  • 1
    Good enough to get the question re-opened!
    – John Conde
    Sep 7 '14 at 3:00

You can do this with a single RewriteRule. The trick here is to only check for valid username characters, not everything (ie. .* - I wouldn't have thought your usernames could literally be anything?). This would also be more efficient since not every request will match and be processed.

For example, assuming your usernames can only consist of upper/lowercase letters and numbers then:

RewriteRule ^([a-zA-Z0-9])$ /remote.php/carddav/addressbooks/$1/contacts [R=301]

This is very similar to your initial attempt. Note that the RewriteRule pattern in per-directory .htaccess files does not begin with a slash, however, if this rule was used in your server config then it would!

This also naturally avoids the rewrite loop since "/remote.php/carddav..." will not match as a valid username (specifically . and / would fail to match).

You could also limit the length of the username, to say between 4 and 20 characters...

  • ^([a-zA-Z0-9]{4,20})$.

If you needed to match any character except a slash (a slash would surely break your destination URL?) then you could use a pattern like:

  • ^([^/]+)$

Problem fixed through one heck of a lot of perseverance. I really should take the time to learn all of mod_rewrite at some point in time…

In short I solved the redirect loop with the following condition:

RewriteCond %{REQUEST_URI} !^/remote.php/

The above condition basically matches everything that isn't remote.php/ANYTHING_HERE

I then used the above RewriteRule

RewriteRule ^(.*)$ /remote.php/carddav/addressbooks%{REQUEST_URI}/contacts [R=301]

The RewriteRule is almost identical to my previous comment with the difference being it uses the actual request (which is a username in my case and includes a slash - / - so does not need one at the end of addressbooks).

The end result is a full permanent redirect and a handy short URL for me to use when accessing carddav.

  • A slight problem with this approach is that you are potentially matching too much (ie. everything) or not enough (eg. the pattern matches an empty username) which is unnecessary and less efficient. If you restrict the pattern then you can do this with a single RewriteRule and still avoid rewrite loops. I've added an answer.
    – MrWhite
    Sep 7 '14 at 13:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.