Remove those trailing slashes from your URIs

September 15, 2006

Though I made the move a few years ago to future-proof everything on this site (and have already discussed that process in way too much detail here), I've never really talked about how I remove trailing slashes from my URIs (e.g., using /projects instead of /projects/). There really is no legitimate technical reason for this, I just think it looks better, and I recently received an e-mail asking how I do it, and so, as usual, I thought I'd explain it here.

I should point out that if you use WordPress, this method will not prevent you from having files (minus the extension) and directories of the same name (i.e., /projects.php and /projects/whatever can still work together).1

I don't currently use the "default" WP .htaccess rules (remember, I work outside of its theme system), but instead have a single RewriteRule that handles all of my archives (yearly, monthly, and individual). That said, my best guess is that the following rules, if placed above the WP-created rules in your .htaccess file, will work just fine with a default install. Let me know if you have any trouble.

RewriteCond %{REQUEST_FILENAME}.php -f
RewriteCond %{REQUEST_URI} !/$
RewriteRule (.*) $1\.php [L]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)/$ /$1 [R=301,L]

These rules accomplish a couple of things, and I'm going to use my gadget page to illustrate them. First of all, this page exists on my server as /gadgets.php, however, when I point to it with /gadgets, the above .htaccess rules tack on the .php extension (behind the scenes) and give it back to the browser as if it were originally called as /gadgets.php, all while leaving the URI intact (i.e., it doesn't add the extension to the actual address).

Second of all, if I were to link to the gadget page with /gadgets/ (as myself and others have done in years past) and there wasn't a true directory named "gadgets," the rules would remove the slash (both in the address and behind the scenes), tack on the .php extension (behind the scenes), and process it as gadgets.php. To see this, simply go to the gadget page, which you'll notice is linked to here with the trailing slash; you'll see that the slash is removed, no file extension is added, and the page is ultimately processed as it should be.


  1. Not sure if this would work quite right with Movable Type's dynamic publishing option.   

You should follow me on Twitter here