Forum Moderators: phranque

Message Too Old, No Replies

RewriteRules for both .html and .php for extensionless site

         

sailOn

7:16 pm on Aug 30, 2010 (gmt 0)

10+ Year Member



I'm new at .htaccess and I'm trying to get my site to work with extensionless urls and extensionless links. The site has both php & html files and these are in the same directory, limiting my .htaccess options, if I understand e.g. ForceType, e.g.

All the site's links are written without the file extension (which my research indicated generally was the culprit when the rewrite rule for the html didn't work).

I can get the php files to work, extensionlessly, using a RewriteRule, but the RewriteRule for .html doesn't work correctly & I'm not sure where I'm going wrong, after extensive searching on the net and experimenting on my site.

I've used the RewriteRules below:

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^(.*)$ $1.php

#RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d #won't work with/without this
RewriteCond %{REQUEST_FILENAME}\.html -f
RewriteRule ^(.*)$ $1.html

The html files produce a dialog box that says "do you want to save this file or find a program online to open it?"

I added the force type flags, without improvement:

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^(.*)$ $1.php [t=application/x-httpd-php]

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.html -f
RewriteRule ^(.*)$ $1.html [T=text/html]

I added AddType line below to no avail:
AddType application/x-httpd-php .php .htm .html

I also added another one in addition to the above, i.e.
AddType text/html .htm .html
but still received the same dialog box that says "do you want to save this file or find a program online to open it?" when I try to open an html file. If I click on "find" I see:
Windows has the following information about this MIME type.
This page will help you find software needed to open your file.
MIME Type: application/x-httpd-php
Description: UnKnown
Windows does not recognize this MIME type.
If I then bring up a php file by typing its extensionless url, the php file opens without problem.

PHP is run as apache_mod, not cgi, so AddHandler doesn't work (tried it).

ForceType text/html made the php stop working

I'd really appreciate any thoughts about how to get the html rewrite rule to work without causing the php files to no longer work, I'm stumped at where I'm going wrong. Thanks!

jdMorgan

8:14 pm on Aug 30, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



The most likely cause of your trouble is that you tried to escape the literal periods in the RewriteCond -f test strings, and you are missing an [L] flag on your first rule. The combination of these errors was likely fatal, since the files would never be "found" because the REQUEST_FILENAME+\+.php was not the right path.

So let's clean up the mod_rewrite code, and fix a potentially-serious security hole first.

# If the requested extensionless URL does not resolve to an existing directory, but does resolve to
# an existing .php file when ".php" is added, internally rewrite to add ".php" to the filepath
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(([^/]+/)*[^.]+)$ /$1.php [L]
#
# If the requested extensionless URL does not resolve to an existing directory, and does resolve to
# an existing .html file when ".html" is added, internally rewrite to add ".html" to the filepath
RewriteCond %{REQUEST_FILENAME}.html -f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(([^/]+/)*[^.]+)$ /$1.html [L]

Note the much-more-specific negative-match RewriteRule subpatterns, which allow any characters in the directory-path, but do not allow periods or slashes in the final "file" path, and do not allow a blank "file" path, either. This avoids the extremely-inefficient file- and directory-exists checks done by the RewriteConds in most cases; They won't be processed at all unless the RewriteRule pattern matches (See mod_rewrite documentation "Rule processing" section for confirmation & details.)

These rules will now be skipped completely if the final requested URL-path-part contains a period, ends with a slash, or is zero length.

In fact, you should also consider omitting the 'file exists' check for your lesser-used (php or html) filetype, after testing for/rewriting the other more-frequently-requested filetype first. Just rewrite to the lesser-used filetype after checking only that a directory of that name does not exist. It's a bit slower if the end result will be a 404-Not Found, but faster if the file does exist...

Now you may still be left with the MIME-type issue. In that case, I'd suggest using AddType or ForceType on one of the two filetypes, and using the [T=] flag (always along with the [L] flag) for the other. Try it both ways, and check your headers manually using the Live HTTP Headers add-on for Firefox and Mozilla browsers (or something similar).

Also be on the lookout for stray/forgotten AddType and ForceType directives and [T=] flags in subdirectories if you have .htaccess files in those subdirectories, and also for any similarly-forgotten "control panel" MIME-Type settings.

Jim

sailOn

12:37 am on Aug 31, 2010 (gmt 0)

10+ Year Member



Jim,

Thank you so much! The above RewriteConditions and RewriteRules fixed it all. No need to search for the forgotten AddType or ForceType.

To make sure I understand the above, the RewriteConditions in essence are saying if you add .php to the REQUEST-URI it creates an actual file on the site, so when you see that extensionless REQUEST-URI, serve up the .php file. Same for the .html version.

Whenever doing RewriteConditions and RewriteRules, for each set, I should always flag with [L], telling serving that if this one works, stop looking through the .htaccess?

The potential security hole results from the dialog that then opened where someone could save the code?

Again, many, many thanks!

jdMorgan

1:12 am on Aug 31, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



The RewriteConditions in essence are saying "Add .php to the default filepath to which the REQUEST-URI resolves to create an actual filepath in the server's filesystem, and go see if that file exists."

The security problem was the 'naked' $1 as a substitution path. I should not say more in a public forum.

Always use an [L] flag unless you know why you don't want one... This is a usually a rare occurrence, except when using other flags that imply an [L] automatically, like [F], [G], and a few more.

Jim

sailOn

1:41 pm on Aug 31, 2010 (gmt 0)

10+ Year Member



Terrific!

Thank you for the info.

I'm still digesting it, but thrilled that it fixed the problem