user14999963
user14999963

Reputation:

How to make this .htaccess server-friendly and apply to .php?

I don't know anything about .htaccess-files except the very basics.
I copied and pasted this code from different sources in the internet and so far, it works. The code (a) defines the 404-errorpage, (b) defines how long certain files should be "saved", (c) removes the .html-extension from all URLs and (d) adds a trailing slash to them. I just want to know two things:

  1. How can I apply this code not just for .html-files but for .php-files, too? I suspect I have to change line 6, but I'm not sure.
  2. Are there any opinions from more experienced users on how server-friendly this code is? As I said, I just copied the code, but I want to know if there are any unnecessary redirects, possible SEO-penalties or something like that.

This is the code I'm using in the .htaccess-file:

ErrorDocument 404 /404.html
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)/$ $1.html
RewriteRule ^([^/]+)/([^/]+)/$ /$1/$2.html
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !(\.[a-zA-Z0-9]{1,5}|/)$
RewriteRule ^(.*)$ /$1/ [R=301,L]
<IfModule mod_expires.c>
  ExpiresActive on
  ExpiresByType text/html "access plus 0 seconds"
  ExpiresByType text/css "access plus 1 week"
  ExpiresByType application/javascript "access plus 1 month"
  ExpiresByType application/x-javascript "access plus 1 month"
  ExpiresByType audio/ogg "access plus 1 month"
  ExpiresByType image/gif "access plus 1 month"
  ExpiresByType image/jpeg "access plus 1 month"
  ExpiresByType image/png "access plus 1 month"
  ExpiresByType video/mp4 "access plus 1 month"
  ExpiresByType video/ogg "access plus 1 month"
  ExpiresByType video/webm "access plus 1 month"
  ExpiresByType image/x-icon "access plus 1 month"
</IfModule>

Thank you for your help!

Upvotes: 0

Views: 54

Answers (1)

MrWhite
MrWhite

Reputation: 45889

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)/$ $1.html
RewriteRule ^([^/]+)/([^/]+)/$ /$1/$2.html

You can't simply "change line 6" to handle .php files as well. Since you introduce an ambiguity. For example, should a request for /foo map to .html or .php? You need to prioritise one or the other and check for the presence of the corresponding .php or .html file.

Incidentally, RewriteCond directives only apply to the first RewriteRule directive that follows, so the 2nd RewriteRule directive above is being processed unconditionally. (Although you don't need the "file" check here, since filenames don't end in a slash.)

Also, the handling of one or two path segments (the first and second RewriteRule directives respectively) can be combined into a single rule.

Try the following instead to handle both .html and .php files. I'll assume that .php files take priority. So, if you request /foo and both foo.php and foo.html exist then foo.php will be served (foo.html would only be accessible if you request it directly).

# Rewrite request to ".php" if it exists
RewriteCond %{DOCUMENT_ROOT}/$1.php -f
RewriteRule ^((/?[^/]+){1,2})/$ $1.php [L]

# Otherwise, rewrite request to ".html" if it exists
RewriteCond %{DOCUMENT_ROOT}/$1.html -f
RewriteRule ^((/?[^/]+){1,2})/$ $1.html [L]

Note also the inclusion of the L (last) flag.

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !(\.[a-zA-Z0-9]{1,5}|/)$
RewriteRule ^(.*)$ /$1/ [R=301,L]

These directives could be simplified and optimised by moving the test in the 3rd condition to the RewriteRule pattern and avoid unnecessary filesystem checks.

For example:

# Append trailing slash if omitted
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule !(^$|\.[a-zA-Z0-9]{1,5}|/)$ %{REQUEST_URI}/ [R=301,L]

Also, these rules are arguably in the wrong order (although it probably won't make a difference in this instance). As a general rule, the external redirect (above) should go before the internal rewrites that append the .php or .html extensions, to avoid internal rewrites being inadvertently redirected.

So, in summary, the first part of the file becomes:

ErrorDocument 404 /404.html

RewriteEngine On

# Append trailing slash if omitted
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule !(^$|\.[a-zA-Z0-9]{1,5}|/)$ %{REQUEST_URI}/ [R=301,L]

# Rewrite request to ".php" if it exists
RewriteCond %{DOCUMENT_ROOT}/$1.php -f
RewriteRule ^((/?[^/]+){1,2})/$ $1.php [L]

# Otherwise, rewrite request to ".html" if it exists
RewriteCond %{DOCUMENT_ROOT}/$1.html -f
RewriteRule ^((/?[^/]+){1,2})/$ $1.html [L]

Then followed by the mod_expires directives...

ExpiresByType application/javascript "access plus 1 month"
ExpiresByType application/x-javascript "access plus 1 month"

Only one of these directives is required. Your server will either be serving JS files with a application/javascript mime-type OR application/x-javascript. It cannot (should not) be both. Most probably the former.

...how server-friendly this code is? As I said, I just copied the code, but I want to know if there are any unnecessary redirects, possible SEO-penalties or something like that.

Not sure what you mean by "server-friendly". But otherwise, whether this works as intended, without unnecessary redirects is really dependent on the URL structure throughout your site, so only you can really answer this... test test test.

But otherwise, it looks OK after these updates.

Upvotes: 1

Related Questions