0

I have the following code in my htaccess file:

Options +FollowSymLinks -MultiViews
RewriteEngine On
RewriteBase /

#vanity URL
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([a-zA-Z0-9-_]*)$ /profile.php?username=$1 [L,QSA]
RewriteCond %{THE_REQUEST} \ /profile\.php\?username=([^&\ ]+)&?([^\ ]*)
RewriteRule ^ /%1?%2 [L,R=301]

#remove file extensions
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^\.]+)$ $1.php [NC,L]


ErrorDocument 400 /404.php
ErrorDocument 401 /404.php
ErrorDocument 403 /404.php
ErrorDocument 404 /404.php 
ErrorDocument 500 /404.php

<Files .htaccess>
order allow,deny
deny from all
</Files>

Regarding the vanity URLs, it works fine, but when it comes to remove the php extensions at the end of the URLs, it doesn't work:

1. if i enter mysite.com/home.php, i do get redirected to home.php but the extension is still there in the address bar.

2. if i enter mysite.com/home, i get redirected to my custom error page because home is not a username is my database.

How can I fix 1. and 2. ?

Caro_deb
  • 279
  • 1
  • 8
  • 25

1 Answers1

1

You need to do the php extension check before the username routing. This, of course, will break if you happen to have a php file that is the same as a username, no way around this unless you prefix all of your usernames.

So swap your rules around and add another rule for redirecting direct accesses to php files:

# we don't want to mess with /profile.php access because there's a rule later that deals with that
RewriteCond %{REQUEST_URI} !^/profile\.php
RewriteCond %{THE_REQUEST} \ /(.*)\.php(\?|\ |$)
RewriteRule ^ /%1 [L,R=301]

# add file extensions back to URI
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^([^\.]+)$ $1.php [NC,L]

#vanity URL
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([a-zA-Z0-9-_]*)$ /profile.php?username=$1 [L,QSA]
RewriteCond %{THE_REQUEST} \ /profile\.php\?username=([^&\ ]+)&?([^\ ]*)
RewriteRule ^ /%1?%2 [L,R=301]

What I mean by the prefix for users is something like this:

http://mysite.com/u/foobar

Here, the /u/ indicates that "foobar" is a user, and not a php page. To do this, you'll need to add a few changes to the "# vanity URL" section:

#vanity URL
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^u/([a-zA-Z0-9-_]*)$ /profile.php?username=$1 [L,QSA]
RewriteCond %{THE_REQUEST} \ /profile\.php\?username=([^&\ ]+)&?([^\ ]*)
RewriteRule ^ /u/%1?%2 [L,R=301]

essentially including /u/ as part of the match and redirect.

Jon Lin
  • 142,182
  • 29
  • 220
  • 220
  • +1 for this good explanation ! I'm going to block usernames such as about, settings etc... so I wont need the prefix. Your code seem to work for the pages, but it doesn't work with my form action files :my forms are not being submitted anymore. if home.php has a form with a form action file "signup.php", i get redirected to mysite.com/signup and then nothing. Any ideas why ? – Caro_deb Oct 03 '13 at 01:00
  • Maybe it would be easier to remove the file extensions for only some specified URLs such as: home.php and account.php. Is this possible via htaccess? – Caro_deb Oct 03 '13 at 01:01
  • 1
    @ChHr in the first rule, the `(.*)` would need to be `(home|account)` and the second rule `([^\.]+)` would need to be `(home|account)`. – Jon Lin Oct 03 '13 at 01:03