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:
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!
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.