7

I am using Apache to serve a blog which consists of static HTML files. Currently, the blog uses a pretty standard URL structure, like this:

/2010/03/21/my-awesome-blog-post/

which maps to the file

/2010/03/21/my-awesome-blog-post/index.html

using Apache's mod_dir.

I'd like to remove the trailing slash so that URLs like

/2010/03/21/my-awesome-blog-post

work in the same way (and don't get redirected). Is there a way to do that with Apache?

(Note that I want URLs with the trailing slash to continue to work, as well.)

(Further note: I saw something about Apache's DirectorySlash directive, but I don't think it does what I want … although I'm not sure about that.)

unor
  • 246
  • 2
  • 19
mipadi
  • 315
  • 2
  • 3
  • 11

6 Answers6

12

The Apache Rewrite Guide has a chapter on the "Trailing Slash Problem" (scroll down a bit) explaining how to solve the issue with the trailing slashes in general.

However, they also state that the trailing slash is required for directories when the rendered page in it uses resources (images, stylesheets, ..) with relative links - which will not work without the slash:

"The solution to this subtle problem is to let the server add the trailing slash automatically. To do this correctly we have to use an external redirect, so the browser correctly requests subsequent images etc. If we only did a internal rewrite, this would only work for the directory page, but would go wrong when any images are included into this page with relative URLs, because the browser would request an in-lined object. For instance, a request for image.gif in /~quux/foo/index.html would become /~quux/image.gif without the external redirect!"

Chris S
  • 77,945
  • 11
  • 124
  • 216
Axel Knauf
  • 1,600
  • 1
  • 10
  • 12
7

You could always use mod_rewrite to redirect the directory name without the trailing slash to dirname/index.html. You could use RedirectConds to make sure that redirection doesn't get done if the URL ends with a trailing slash or with .html, and that it only applies specifically to blog post URLs.

Let me whip up an example, this'll take a moment.

# Trailing slashes and .html suffix
RewriteCond !/$
RewriteCond !\.html$

# Check if it's actually a dir and if index.html exists
RewriteCond %{REQUEST_URI} -d
RewriteCond %{REQUEST_URI}/index.html -f

# Rewrite anything that gets through (Probably insecure, but you get the idea)
RewriteRule ^(.*)$ $1/index.html

Edit: Can also be combined with Matt's solution of adding the redirect error code to the RewriteRule. It should probably also be made the last RedirectRule. Refer to the mod_rewrite documentation for more.

  • 2
    `RewriteCond: bad argument line '!/$'` – Michael Oct 09 '14 at 22:07
  • 1
    @Michael Newer versions of Apache need `RewriteCond %{REQUEST_URI} !/$`, as well as `RewriteCond %{REQUEST_FILENAME} -d` and `RewriteCond %{REQUEST_FILENAME}/index.html -f`. The `!\.html$` should also be changed to `RewriteCond %{REQUEST_URI} !\.html$`, but I don't think this adds much to the rule. Also, don't forget to turn off the default mechanism which adds the slash in the first place: `DirectorySlash Off` and to enable mod_rewrite (`a2enmod rewrite` + `RewriteEngine on`). – Suzanne Soy Feb 25 '16 at 12:42
  • @GeorgesDupéron "Newer versions of Apache need..." that's **all** versions of Apache! ;) – MrWhite Mar 13 '16 at 01:58
3

Did you read the definition of the DirectorySlash?

The DirectorySlash directive determines, whether mod_dir should fixup URLs pointing to a directory or not.

Typically if a user requests a resource without a trailing slash, which points to a directory, mod_dir redirects him to the same resource, but with trailing slash for some good reasons:

  • The user is finally requesting the canonical URL of the resource
  • mod_autoindex works correctly. Since it doesn't emit the path in the link, it would point to the wrong path.
  • DirectoryIndex will be evaluated only for directories requested with trailing slash.
  • Relative URL references inside html pages will work correctly.

Well, if you don't want this effect and the reasons above don't apply to you, you can turn off the redirect with:

# see security warning below!
<Location /some/path>
DirectorySlash Off
SetHandler some-handler
</Location>
unor
  • 246
  • 2
  • 19
Tyrael
  • 176
  • 1
  • 5
  • 1
    Yes, but that's not the whole story. If you have a file like `/some-dir/index.html` and request `/some-dir` (no trailing slash) then you'll receive a 404 page in response. This can be fixed with rewrites, but I wondered if there was an option to do it automatically. (Also, geez, no need to be a smart ass about it.) – mipadi Mar 29 '11 at 18:22
2

Removing index.php from URL can be done by writing only two lines in your .htaccess (mod_rewrite in Apache) file. Before writing the rules in .htaccess, make sure that mod_rewrite is enabled (RewriteEngine On) in your Apache server. Most probably mod_rewrite is enabled in a Linux server, but for a windows server you might need to contact the hosting people to enable mod_rewrite. You can check this by looking in phpinfo().

Below are the rules which will remove index.php from the URL:

RewriteCond %{THE_REQUEST} ^[A-Z]{3,9} /([^/]+/)*index.php HTTP/ 
RewriteRule ^(([^/]+/)*)index.php$ http://www.%{HTTP_HOST}/ [R=301,NS,L]

Redirect 301 means "Moved Permanently" so most search engines will remove index.php from the URL.

Matt
  • 579
  • 5
  • 11
  • 24
1

I had the same problem, but I was using mod_alias to set up a subsite. Turns out, I needed to make a second alias without the trailing slash so that it would work correctly. Looked something like this:

Alias /forum/ "/var/www/forum"
Alias /forum "/var/www/forum"

<Directory "/var/www/forum">
    Options FollowSymlinks
    AllowOverride None
    Order allow,deny
    Allow from all
</Directory>

In Ubuntu, I had to edit the /etc/apache2/mods-enabled/alias.conf file with these lines, then restart apache. Couldn't find this answer anywhere on the web; I just stumbled onto it myself as mod_rewrite wasn't working and the DirectorySlash command didn't help either. I was appending a non-Drupal program as a subsite under a Drupal installation, which is what kicked off all this madness in the first place...

John K
  • 11
  • 1
0

You might want to try an Alias: http://httpd.apache.org/docs/2.0/mod/mod_alias.html

pors
  • 111
  • 4