Search code examples
apache.htaccessmod-rewrite

adding forward slash after rewrite if not exist


I have read a ton and tried a ton of solutions, but can't find one specific to my needs.

In my htaccess I have the following:

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^profile/([\w-]+)/?$ profile.php?username=$1 [L,QSA]
RewriteRule ^profile/([\w-]+)/([\w-]+)/?$ profile.php?username=$1&type=$2 [L,QSA]
RewriteRule ^profile/([\w-]+)/([\w-]+)/([\w-]+)/?$ profile.php?username=$1&type=$2&o=$3 [L,QSA]

This works wonderfully, except for 1 small problem.

If profile/username does not have a / the links on the page will break unless absolute urls are used. So <a href="./1"> will end up as profile/1 instead of profile/username/1

If I change the first rewrite to the following:

RewriteRule ^profile/([\w-]+)/$ profile.php?username=$1 [L,QSA]

then https://myurl/username will return a 404 which I do not want - I want it to force the / on the end if it does not exist.

I have tried adding:

RewriteRule ^(.*)([^/])$ /$1$2/ [L,R=301] 

I have tried

RewriteRule ^(.*)$ https://nmyurl/$1/ [L,R=301]

Just can't figure out how to do this with the rewrite conditions already in place.


Solution

  • So unfortunately I wasn't able to actually achieve what I was hoping to because there are multiple levels of variables that may or may not exist.

    In part I used the solution provided by Amit:

    RewriteCond %{REQUEST_URI} ^/profile/
    RewriteRule !/$ %{REQUEST_URI}/ [L,R]
    

    However this wasn't enough, because as pointed out by MrWhite there are 3 separate potential url's.

    https://myurl/profile/username/
    https://myurl/profile/username/type/
    https://myurl/profile/username/type/o/
    

    In this sitation username should always exist, but type and o may or may not exist.

    So what I did was detect the level of the url and then created conditional . and .. using php.

    The variable o is always numeric and variable type is never numeric so this worked for me.

    if (isset($_GET['o'])) { $o = strip_tags($_GET['o']); }
    elseif (isset($_GET['type']) && is_numeric($_GET['type'])) { $o = strip_tags($_GET['type']); }
    

    Then I detect:

    // if o is set or if type is numberic, use ..
    if (isset($_GET['o']) || (isset($_GET['type']) && is_numeric($_GET['type']))) {
      $dots = '..';
    // if o is not set and type is not numeric just use .
    } else {
      $dots = '.';
    }
    

    end result of <a href="'.$dots.'/1/">1</a>:

    if url is https://myurl/profile/username/
    result is https://myurl/profile/username/1/
    
    if url is https://myurl/profile/username/3/
    result is https://myurl/profile/username/1/
    
    if url is https://myurl/profile/username/type/3/
    result is https://myurl/profile/username/type/1/
    

    Which was the desired outcome.