views:

104

answers:

3

Here's a recurring problem. There are similar questions on SO about this, but nothing quite answers my question.

I've got a website and I want every page to be available at only one URL. It should work dynamically on all pages, not on a sinlge hard-coded filename.

  1. domain.tld/foo should redirect to domain.tld/foo/
  2. domain.tld/foo.php should redirect to domain.tld/foo/
  3. domain.tld/foo/ should give the user (but not redirect him to) domain.tld/foo.php

1 and 3 are not too hard, but I can't figure out 2 without introducing a circular reference and failing with too many redirects. How would I be able to do this?

+1  A: 

Rewriting #1 is taken care of by

DirectorySlash on

which should be the default anyway.

For #2 and #3:

RewriteRule /(.+).php /$1/ [R=301,L]
RewriteRule /(.+)/ /$1.php
David Zaslavsky
The `DirectorySlash` is nice, thanks for that. The rest gives me infinite redirects for `foo/bar/` and `foo/bar.php`, while `foo/bar` leads to `foo`.
avdgaag
Hm, I thought from the question that you wanted this for single-component URLs.
David Zaslavsky
A: 

If my understanding right, your problem is similar to what I had to face when I posted a question here http://stackoverflow.com/questions/1178405/how-can-i-detect-if-page-was-requested-via-a-redirect

Although we couldn't find an answer entirely solving the issue, still some of the replies there may be helpful to you.

G Berdal
+2  A: 

Try these three rules:

RewriteCond %{THE_REQUEST} ^GET\s/[^?\s]+\.php[?\s]
RewriteRule (.+)\.php$ /$1/ [L,R=301]
RewriteCond $0 !.+\.php$
RewriteRule (.*[^/])$ /$1/ [L,R=301]
RewriteRule (.+)/$ $1.php [L]

And to exclude any other existing file, put this rule in front of the others:

RewriteCond %{REQUEST_FILENAME} -f
RewriteRule !.+\.php$ - [L]
Gumbo
Thanks, but this rewrites all URLs to `foo.php/`. They all point to the same location, which is good, but I want to get rid of the `.php`. I'm still tinkering with it.
avdgaag
@avdgaag: Fixed it.
Gumbo
@Gumbo: awesome, this worked. Thanks a lot!
avdgaag