How to remove trailing slashes from URL with .htaccess?

46,943

Thanks for your time to look at the question, but we appeared to have figured it out:

Options -Multiviews -Indexes +FollowSymLinks
RewriteEngine On
RewriteBase /
DirectorySlash Off

# remove trailing slash
RewriteRule ^(.*)\/(\?.*)?$ $1$2 [R=301,L]

# rewrite /dir/file?query to /dir/file.php?query
RewriteRule ^([\w\/-]+)(\?.*)?$ $1.php$2 [L,T=application/x-httpd-php]

We have to turn off Multiviews and Indexes so the engine doesn't get confused and instead try to reference any index.* file or show a directory listing (also confusingly called an "index" with Apache...) when a directory appears to be requested.

The first redirect visibly (R=301) removes the trailing slash, and the second one internally rewrites it to the PHP (or HTML, etc.) file at hand.

This .htaccess file also supports query strings.

Update As noted in the comments below much earlier, we've switched to nginx, and this is all our conf file contains related to URL-rewriting (from my dev box):

location = / {
    index index.html;
}

try_files $uri $uri.html =404;

We've also switched from PHP to just plain HTML, but changing the extensions above should hardly make a difference, if at all.

Share:
46,943

Related videos on Youtube

Matt
Author by

Matt

Updated on September 18, 2022

Comments

  • Matt
    Matt over 1 year

    The situation

    Across the entire domain, we'd like the URLs to hide file extensions and remove trailing slashes, independent of the domain name itself (as in, works on any domain).

    Sample of our directory structure

    We're not using index.* files except for the homepage.

    • /
      • /index.php
      • /account.php
      • /account
        • /subscriptions.php
      • /login.php
      • /login
        • /reset-password.php

    The goal

    Some examples of how these files might be requested, and how they should look in the browser:

    • / and index.php --> mydomain.com (literally just the bare domain name).

    • /account.php or /account/ or /account --> mydomain.com/account

    • /account/subscriptions.php or /account/subscriptions/ or /account/subscriptions --> mydomain.com/account/subscriptions

    As you can see, there are several ways to access each webpage, but no matter which of the 2 or 3 ways you use to get there, it only shows the one preferred URL in the browser.

    The question

    How is this done with .htaccess using mod_rewrite?

    I've banged my head against the wall trying to figure this out, but in general, the rewrite flow would seem to be something like this:

    1. External 301 redirect ( mydomain.com/account/ --> mydomain.com/account )
    2. Internally append .php ( mydomain.com/account --> mydomain.com/account.php )

    I've been Googling this all day, read thousands of lines of documentation and config texts, and have tried several dozen times... I think more brains on this would help a lot.

    UPDATE

    We found an answer our question (see below).

  • Matt
    Matt over 12 years
    We thought about something like this (thanks for the links), but our development version of the site is PHP-powered and the deployed production site is 100% static (no PHP). This .htaccess file will be fore the deployed production site.
  • urasandesu
    urasandesu over 12 years
    It would be very easy to quickly create a static site based on these micro-frameworks. The project I used them for was mostly static content, with just a splash of PHP used to bootstrap the site using the micro-framework. Depending on the size of the site, converting it to use a micro-framework might be faster than banging your head against .htaccess all day.
  • Matt
    Matt almost 12 years
    In hindsight, we've switched to nginx and this whole task was SUPER-easy...
  • MrWhite
    MrWhite over 11 years
    Minor point, but you don't need to escape the forward slash (/) in the regex, as it carries no special meaning. \/ is the same as '/'.
  • Matt
    Matt over 11 years
    @w3d Good point. That's a habit from my Javascript regex'ing.