how to: htaccess for Apache
As a web designer or developer, it is important to know how to use the htaccess file to your advantage. It is a very powerful tool, and can even work as a deterrent for bandwidth thieves, exploits, and hackers. Below are some common examples of rules to consider when developing websites. We hope you find them useful.
Jump To Redirect Example
- Rewrite Engine
- Basic Redirect
- HTML to PHP
- Remove File Extensions
- Add WWW To Domain
- Remove WWW From Domain
- Add Trailing Slash
- Remove Trailing Slash
- Remove Query String
- Remove Trailing Question Mark
- Remove Trailing Index File
- Remove Index File From URL
- HTTP to HTTPS
- HTTPS to HTTP
- Deny Access To Htaccess
- Enable Caching
- Disable Caching On Dynamic Pages
- Example Htaccess File
Rewrite Engine
In order for any of these rules to work, the first thing we need to do is turn on the rewrite engine.Options +FollowSymLinks
RewriteEngine On
Basic Redirect
There are a couple reasons why you would use a basic redirect. Let’s say you just re-structured and organized your files, but you wanted visitors who were still using the old filename to be able to access the new one. They might have bookmarked the page, or found it in a search engine.RewriteRule ^old-filename.php$ /new-filename.php [R=301,L]
[R]
without adding the code parameter, the code would have been a 302, which is a temporary redirect. We want to use a permanent one so search engines know that the old file does not exist anymore.
There is also a caret in front of old-filename.php and a dollar sign at the end. These are regular expressions, and the caret tells us to the request must start with this, while the dollar sign means it must end with this. We will talk more about flags and regular expressions in an upcoming article.
The last thing we want to point out is the forward slash in front of new-filename.php. If we were to specify the base path for rewriting, we would not need this, but since we did not, we need to add it. If we wanted to drop it though, we would add the following directive after we turn the rewrite engine on:
RewriteBase /
Redirect 301 /old-filename.php http://www.domain.com/new-filename.php
Redirect Permanent /old-filename.php http://www.domain.com/new-filename.php
Redirect /old-filename.php http://www.domain.com/new-filename.php
Redirect 302 /old-filename.php http://www.domain.com/new-filename.php
Redirect Temp /old-filename.php http://www.domain.com/new-filename.php
Redirect
, it will use the default temporary redirect (a 302), just like our redirect flag.
HTML to PHP
What if we recently converted our site to PHP, but all of the old filenames were using the .html extension? It wouldn’t make sense to create a redirect rule for each file. So instead we could do this:RewriteRule ^(.*).html /$1.php [R=301,L]
AddType application/x-httpd-php .php .html .htm
Remove File Extensions
But file extensions are so ugly! Maybe you want to give the illusion that your individual files are actually directories:RewriteRule ^(.*)/$ /$1.php [L]
http://www.domain.com/services.php
http://www.domain.com/products.php
http://www.domain.com/about.php
http://www.domain.com/links.php
http://www.domain.com/contact.php
http://www.domain.com/services/
http://www.domain.com/products/
http://www.domain.com/about/
http://www.domain.com/links/
http://www.domain.com/contact/
Add WWW To Domain
One of the first things you should decide when you create a new site, or at least early on, is if you’re going to have the WWW in your domain or not. This is important not only aesthetically, but for search engine optimization. By forcing visitors and search engines to your preferred domain, you can guarantee that you won’t end up with duplicate results or different page ranks for your domain with or without the WWW. I personally think domains look naked without them, and there is a reason why we use the WWW in the first place. See, not everyone enters the WWW when they type in a domain. Some leave it out, while others always type it in. If you’re familiar with the keyboard shortcuts built in to your browser, simply typing the domain without the TLD extension (e.g. domain instead of domain.com) and then holding CTRL + Enter will add the www. before the domain name, and a .com after it (other keyboard shortcuts will use .org or .net). You might have been to a site before and noticed that if you don’t type the WWW in, you get an error page telling you that the page cannot be found. It all depends on how your host or server administrator has decided to set this up, but usually your domain will work with or without the WWW.RewriteCond %{HTTP_HOST} ^domain.com$ [NC]
RewriteRule ^(.*)$ http://www.domain.com/$1 [R=301,L]
NC
flag at the end of the first line just means to ignore the case of what the request is, so we could type in DoMain.com and it wouldn’t matter. The R=301
flag means we are going to visually redirect the visitor to our domain with the WWW.
A 301 code is a permanent redirect, and that is important because it also tells search engines that this isn’t a temporary thing (which is what a 302 code would be).
The L
flag means this is the last rule to follow in this set. Any other rules or conditions after this will not be factored into this rule.
Remove WWW From Domain
Others prefer to remove the WWW, and for this rule, we’re just doing the exact opposite of the previous example.RewriteCond %{HTTP_HOST} ^www.domain.com$ [NC]
RewriteRule ^(.*)$ http://domain.com/$1 [R=301,L]
Add Trailing Slash
The use of a trailing slash is also important to consider. By default, your web browser will add a trailing slash to the end of a URL. It makes sense to have the trailing slash too—except for files—because it means we’re in a directory.RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !(.*)/$
RewriteRule ^(.*)$ http://www.domain.com/$1/ [R=301,L]
R
and L
flag here like we did in the previous two examples. You will see both of these flags throughout our examples.
There are times when you do not want the trailing slash. For example, if you do a search on the Crucial Domain Finder, you will notice that there is no trailing slash. Whatever is at the end of the URL is the query that our script is looking at.
If you want to do something like this, we can specify which directories to not apply this rule to.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !directory/(.*)$
RewriteCond %{REQUEST_URI} !(.*)/$
RewriteRule ^(.*)$ http://www.domain.com/$1/ [R=301,L]
DirectorySlash Off
Turning off the trailing slash redirect may result in an information disclosure. Consider a situation where mod_autoindex is active (Options +Indexes) and DirectoryIndex is set to a valid resource (say, index.html) and there’s no other special handler defined for that URL. In this case a request with a trailing slash would show the index.html file. But a request without trailing slash would list the directory contents.If you are adding a trailing slash to everything, then you don’t even need to use this rewrite rule, but if you wanted to have a specific directory not receive a slash, you are going to want to add this slash rule and then this directive.
Remove Trailing Slash
Just like with the WWW example, some prefer to remove the trailing slash. It’s a commonly debated question that you’ll find around the Internet, but it just depends on what you prefer. Remember though, your browser and even your server, by default, add a trailing slash to a directory. It is done for a reason. If you must strip the trailing slash though, this is how you would do it:RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !(.*)$
RewriteRule ^(.*)$ http://www.domain.com/$1 [R=301,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !directory/(.*)$
RewriteCond %{REQUEST_URI} !(.*)$
RewriteRule ^(.*)$ http://www.domain.com/$1 [R=301,L]
DirectorySlash
directive in the previous example. You might need to turn this directive off.
Remove Query String
If you’ve taken the time to convert your ugly URLs to pretty ones, you may not want people typing in query strings. This rule will strip any query string attached to the end of a URL.RewriteCond %{QUERY_STRING} .
RewriteRule ^(.*)$ http://www.domain.com/$1? [R=301,L]
Remove Trailing Question Mark
Sometimes a rogue question mark will remain at the end of your URL. It’s certainly not pretty, and this rule will make sure you never see it again.RewriteCond %{THE_REQUEST} ? HTTP [NC]
RewriteRule .? http://www.domain.com%{REQUEST_URI}? [R=301,L]
Remove Trailing Index File
With more sites and freely available PHP software using rewritten URLs, a lot of people don’t like to have any files in their URL. With the index.php file being the most common, we can strip this out of the URL. A common place for this is the very root of your website:www.domain.com/index.php becomes www.domain.com
RewriteCond %{THE_REQUEST} /index.php HTTP
RewriteRule (.*)index.php$ /$1 [R=301,L]
RewriteCond %{THE_REQUEST} /index.(php|html) HTTP
RewriteRule (.*)index.(php|html)$ /$1 [R=301,L]
Remove Index File From URL
You might have been to a website where the URL looks something like this:http://www.domain.com/index.php/blog/my-first-article/Blogs and CMS applications typically have an index file that handles all of the requests, which is why you see this. It’s definitely worthless, and quite ugly. Not a problem though, we can easily remove that.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php/$1 [L]
HTTP to HTTPS
This comes in handy if you have something like a secure order form or login area. On Crucial, we have two areas where the HTTPS protocol is used, the client login area and the order form. We can make sure people are using the secure version for these sections with the following rule. Just replace the word “directory” on the second line with the name of the directory that needs to use the secure version.RewriteCond %{HTTPS} !=on
RewriteRule ^directory$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
HTTPS to HTTP
If visitors to your site are leaving a secure area and say, going back to other, non-secure portions of your site, it’s a good idea to make sure that we go back to the standard HTTP protocol. On the second line, we would enter the name of the directory where we do not want to send visitors to the non-secure version. It is most likely going to be the same as the directory you entered in the previous example.RewriteCond %{HTTPS} =on
RewriteCond %{REQUEST_URI} !^/directory
RewriteRule ^(.*)$ http://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
Deny Access To Htaccess
If you don’t want people looking at your .htaccess file, then this rule will take care of that.order allow,deny
deny from all
Enable Caching
It’s a good idea to cache files that hardly ever change. How long the caching lasts for is up to you. If you change things up frequently, try an hour or two. In this example, we’re caching media, JavaScript, and CSS files.# 1 Hour = 3600
# 1 Day = 43200
# 1 Week = 604800
# 1 Month = 2592000
# 1 Year = 29030400
Header set Cache-Control "max-age=2592000, public"
Disable Caching On Dynamic Pages
There are times when you want to disable caching completely, and you would typically do this for dynamic pages that change a lot, like a blog article or forum post.Header set Cache-Control "max-age=0, private, no-store, no-cache, must-revalidate"
Example Htaccess File
Now that we’ve seen examples for individual rules, here is what your htaccess file might look like:Options +FollowSymLinks
RewriteEngine On
##### Add WWW ###############################################
RewriteCond %{HTTP_HOST} ^domain.com$ [NC]
RewriteRule ^(.*)$ http://www.domain.com/$1 [R=301,L]
##### Remove query string ###################################
RewriteCond %{QUERY_STRING} .
RewriteRule ^(.*)$ http://www.domain.com/$1? [L]
##### Remove trailing question mark #########################
RewriteCond %{THE_REQUEST} ? HTTP [NC]
RewriteRule .? http://www.domain.com%{REQUEST_URI}? [R=301,L]
##### Remove trailing index file ############################
RewriteCond %{THE_REQUEST} /index.php HTTP [NC]
RewriteRule (.*)index.php$ /$1 [R=301,L]
##### Add trailing slash ####################################
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !(.*)/$
RewriteRule ^(.*)$ http://www.domain.com/$1/ [R=301,L]
##### Deny access to htaccess ###############################
order allow,deny
deny from all
##### Cache media files #####################################
Header set Cache-Control "max-age=2592000, public"
##### Don't cache dynamic pages #############################
Header set Cache-Control "max-age=0, private, no-store, no-cache, must-revalidate"