Search code examples
apache.htaccesssilverstripesilverstripe-4

SilverStripe 4 - Remove slash at the end of the URL


I've been trying for some time to delete the slash at the end of the URL link, but it doesn't work. I searched a lot of examples but none of them solve my problem.

I'm using Silverstripe 4 and currently running on a local server. I have to remove the slash for SEO reasons.

My current URL is:

www.example.com/
 
// Need to be like below 

www.example.com

I try via htaccess

Exampe from stackoveflow question

I put in /public/.htaccess

RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ /$1 [L,R] # <- for test, for prod use [L,R=301]

and when i visit homepage slash is there at the end.

I try via code in SiteTree

public function Link($action = null)
 {
   return rtrim(parent::Link($action), '/');
 }

Above code remove slash at the end from all pages but on home page still there.

www.example.com/about-us (here removed)
www.exaple.com/ (here exists)

And also try via config file

Director::config()->set('alternate_base_url', rtrim(Environment::getEnv('SS_BASE_URL'), '/'));

But again slash exists at the end of the url on homepage.

Does someone have solution for this? Thanks!

Here is my full htaccess file

<IfModule mod_rewrite.c>

    # Turn off index.php handling requests to the homepage fixes issue in apache >=2.4
    <IfModule mod_dir.c>
        DirectoryIndex disabled
        DirectorySlash On
    </IfModule>

    SetEnv HTTP_MOD_REWRITE On
    RewriteEngine On

    # Enable HTTP Basic authentication workaround for PHP running in CGI mode
    RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

    # Deny access to potentially sensitive files and folders
    RewriteRule ^vendor(/|$) - [F,L,NC]
    RewriteRule ^\.env - [F,L,NC]
    RewriteRule silverstripe-cache(/|$) - [F,L,NC]
    RewriteRule composer\.(json|lock) - [F,L,NC]
    RewriteRule (error|silverstripe|debug)\.log - [F,L,NC]

    # Process through SilverStripe if no file with the requested name exists.
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule .* index.php


    # REMOVE SLASH AT THE END OF THE URL

    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^(.*)/$ /$1 [L,R] # <- for test, for prod use [L,R=301]

</IfModule>

Solution

  • www.example.com/
     
    // Need to be like below 
    
    www.example.com
    

    What you are trying to do is not possible! You are trying to remove the slash at the start of the URL-path, immediately after the hostname. This is not the same as the slash at the end of the URL-path.

    There is always a slash at the start of the URL-path, even if you don't always see this in the browser's address bar (the browser often "prettifies" the URL you see in the address bar). This is necessary in order to form a valid HTTP request.

    Whether you request www.example.com (no slash) or www.example.com/ (with slash), the user-agent/browser actually makes the exact same request to the server, ie. www.example.com/ (note that Google Chrome never displays the trailing slash after the hostname in the address bar, aka "omnibox", even if you type it in). If you look at the first line of the HTTP request headers you will see something like the following in both cases:

    GET / HTTP/1.1
    

    Note the first slash (delimited by spaces) - that represents the URL-path. It is not valid to have nothing here (eg. GET HTTP/1.1 is not a valid HTTP request).

    This is different to removing the slash at the end of the URL-path, eg. www.example.com/about-us/ to www.example.com/about-us. In this case the trailing slash is just another character. (Although there is naturally a complication when the URL-path maps to a physical directory since mod_dir will (by default) always append a trailing slash in this instance.)

    See also my answer to the following question on the Webmasters Stack for more detail:

    Further reference:


    I try via htaccess

    Attempting to remove the slash from the start of the URL-path will result in a redirect loop since the user-agent will correct the request each time. For the request to have reached your server then there must have been a slash at the start of the URL-path (ie. after the hostname).

    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^(.*)/$ /$1 [L,R]
    

    The homepage, ie. document root, is a directory so the condition fails and the rule is not processed.

    But the pattern ^(.*)/$ will only successfully match a non-empty URL-path. And /$1 naturally redirects with a slash prefix. To omit the slash you would need to do something like this:

    # DON'T DO THIS
    RewriteRule ^$ https://www.example.com [R,L]
    

    But this is nonsense and will result in a redirect loop, for the reasons mentioned above.