Drop trailing slash in apache for directory

.htaccessApache2mod-rewriterewriterewritecond

I have the following url www.example.com/advice/ now notice the trailing slash at the end of the url? I would like that to be removed to be something like www.example.com/advice. Now when I enter that URL in the browser I get redirected to the with trailing slash, even with curl for example. Now I know the trailing slash is getting added because advice is an actual directory.

[steve@dev dev.www.example.com]$ curl -I  https://dev.www.example.com/advice -k
  HTTP/1.1 301 Moved Permanently
  Date: Fri, 25 Nov 2016 08:20:11 GMT
  Server: Apache/2.4.6 (CentOS)
  Location: https://dev.www.example.com/advice/
  Cache-Control: max-age=0
  Expires: Fri, 25 Nov 2016 08:20:11 GMT
  Connection: close
  Content-Type: text/html; charset=iso-8859-1

[steve@dev dev.www.example.com]$ curl -I https://dev.www.example.com/advice/ -k
HTTP/1.1 200 OK
Date: Fri, 25 Nov 2016 08:21:19 GMT
Server: Apache/2.4.6 (CentOS)
X-Powered-By: PHP/5.6.27
Set-Cookie: flarum_session=mfbou2hcbvcobhncnaqlvl9bm7; Path=/; HttpOnly
X-CSRF-Token: WV69M1oi8POqOcXi6MvwKhbJQ72Tmo2WpFn3oxwq
Content-Length: 10339
Cache-Control: max-age=0
Expires: Fri, 25 Nov 2016 08:21:19 GMT
Vary: Accept-Encoding
Access-Control-Allow-Origin: *.example.com
Connection: close
Content-Type: text/html; charset=UTF-8

What I tried so far


Inside of the .htacess I tried:

DirectorySlash Off

Which resulted into a 403 without the slash

[steve@dev dev.www.example.com]$ curl -I https://dev.www.example.com/advice -k
  HTTP/1.1 403 Forbidden
  Date: Fri, 25 Nov 2016 08:53:15 GMT
  Server: Apache/2.4.6 (CentOS)
  Connection: close
  Content-Type: text/html; charset=iso-8859-1

I also added the following rewrite rule but nothing changed

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

More information


Now advice is where I have a forum platform installed, in the same directory I have a CMS installed, something like below

├── advice
│   ├── admin.php
│   ├── api.php
│   ├── assets
│   ├── composer.json
│   ├── composer.lock
│   ├── config.php
│   ├── CONTRIBUTING.md
│   ├── index.php <-- Forum entry point
│   ├── LICENSE
│   ├── Procfile
│   ├── readme.md
│   ├── scripts
│   ├── storage
│   ├── Vagrantfile
│   └── vendor
├── assets
├── cms
├── codeception.yml
├── commands
├── composer.json
├── composer.lock
├── crontask
├── dropzone
├── email-helpers
├── favicon.ico
├── framework
├── gridfield-bulk-editing-tools
├── gridfieldextensions
├── index.php <-- CMS Entry point
├── kickassets
├── liveseo
├── minify
├── README.md
├── reports
├── setup.php
├── shortcodable
├── silverstripe-cache
├── siteconfig
├── _ss_environment.php
├── tests
├── themes
├── trait-loader
├── vendor
└── web.config

Apache version Apache/2.4.6 (CentOS)

You can find the advice .htaccess here and the one in the cms here

If it helps the CMS is silverstripe and forum is flarum

Best Answer

If you remove the slash on a directory and still expect the directory index document (in that directory) to be returned then you'll need to manually "fix" the URL by internally rewriting to the index document. (You basically need to redo what you have undone by turning the DirectorySlash Off.)

Try something like the following before other mod_rewrite directives in the root .htaccess file:

DirectorySlash Off

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -d
RewriteCond %{REQUEST_URI} !/$
RewriteCond %{REQUEST_FILENAME}/index.php -f
RewriteRule (.*) $1/index.php [L]

For all requests for physical directories, that don't end in a slash where index.php exists in that directory then internally rewrite to index.php.

Alternatively, you could just append the trailing slash (via an internal rewrite) and then allow mod_dir to issue a subrequest to the DirectoryIndex. For example:

RewriteRule (.*) $1/ [L]

Assuming you have a DirectoryIndex set (which you probably do have if this was working previously) then mod_dir will then internally rewrite the request (strictly a subrequest) from /advice/ to /advice/index.php. However, this is now a two stage process, so you might as well do this all in one with mod_rewrite (unless you have varying directory index documents).


The above is a general case for all directories. You could be more specific and check only for the directory/URL in question:

RewriteRule ^advice$ advice/index.php [L]

If the request is for /advice then internally rewrite to /advice/index.php - this does not check whether it is a directory, that is just assumed.