8 cool .htaccess tricks

For a lot of people, .htaccess is a complete mystery. Most of us (myself included) basically get by with copying and pasting examples from the internet to do certain tasks in .htaccess without really understanding how or why the file works.

Apache htaccess

In short, .htaccess allows you to override the configuration files stored in apache’s httpd.conf file. This let’s you fine tune Apache’s global configuration file for your specific website’s needs. You can enable and disable almost every one of Apache’s features from this one configuration file.

Let’s dive into some common tasks you can use .htaccess for to help you maintain control of your server.

1. Stopping hot linking of images:

Hot linked images are caused when a user posts an image and instead of hosting the file on their own server, they go out and directly link to the image from your site. While a lot of times the traffic is too low to really be a problem, if the image hits a site with a lot of traffic, or a popular social media post, the consequences in terms of bandwidth and server memory could be huge.

You can prevent image hot linking with a few simple lines in .htaccess:

<IfModule mod_rewrite.c>
    #Block hotlinking
    RewriteCond %{HTTP_REFERER} !^$
    RewriteCond %{HTTP_REFERER} !^http(s)?://(www\.)?mydomain.com [NC]
    RewriteRule \.(jpg|jpeg|png|gif|css)$ - [NC,F,L]

The first two conditions check the HTTP_REFERER server variable, if the referrer does not come from the same domain as your site, the RewriteRule will turn any image request into a null (-), blocking the image from being rendered. You can also decide to redirect the traffic to an image you specify (that might say “Don’t steal images from me”).

    RewriteRule \.(jpg|jpeg|png|gif|css)$ /images/dontsteal.jpe [L]

Notice we change the extension of our image to ‘.jpe’ instead of ‘.jpg’, this is to get around our RewriteRule which blocks ‘.jpg’ extensions from displaying on other websites.

2. Block bad crawlers

Another thing you can use .htaccess for is to block IP addresses of spammers or bad bots. Some web crawlers are written to suck down email addresses or personal information off of websites so they can then sell to spammers or scammers.

To block an IP address simply use the following condition:

    RewriteCond %{REMOTE_HOST} [OR]

To block user-agents use this condition:

    RewriteCond %{HTTP_USER_AGENT} ^Zeus [NC,OR]

Finally the last line should be the RewriteRule to send them to nothing:

    RewriteRule ^.* - [F,L]

3. Optimize the performance of your site

In a previous post I talked about how to optimize a Craft CMS site. In it I discussed modifying .htaccess to turn on gzip compression and to set the max-age expires on your static assets. You can set this on any website, not just Craft!


    <IfModule mod_deflate.c>
     AddOutputFilterByType DEFLATE text/html text/plain text/css application/json
     AddOutputFilterByType DEFLATE application/javascript
     AddOutputFilterByType DEFLATE text/xml application/xml text/x-component
     AddOutputFilterByType DEFLATE application/xhtml+xml application/rss+xml application/atom+xml
     AddOutputFilterByType DEFLATE image/x-icon image/svg+xml application/vnd.ms-fontobject application/x-font-ttf font/opentype

Max-age expires:

# If you don't use filenames to version, lower the CSS  and JS to something like
# "access plus 1 week" or so.

<IfModule mod_expires.c>
 ExpiresActive on

 # Perhaps better to whitelist expires rules? Perhaps.
 ExpiresDefault                          "access plus 1 month"

 # cache.appcache needs re-requests in FF 3.6 (thanks Remy ~Introducing HTML5)
 ExpiresByType text/cache-manifest       "access plus 0 seconds"

 # Your document html
 ExpiresByType text/html                 "access plus 0 seconds"

 # Data
 ExpiresByType text/xml                  "access plus 0 seconds"
 ExpiresByType application/xml           "access plus 0 seconds"
 ExpiresByType application/json          "access plus 0 seconds"

 # Feed
 ExpiresByType application/rss+xml       "access plus 1 hour"
 ExpiresByType application/atom+xml      "access plus 1 hour"

 # Favicon (cannot be renamed)
 ExpiresByType image/x-icon              "access plus 1 week"

 # Media: images, video, audio
 ExpiresByType image/gif                 "access plus 1 month"
 ExpiresByType image/png                 "access plus 1 month"
 ExpiresByType image/jpeg                "access plus 1 month"
 ExpiresByType video/ogg                 "access plus 1 month"
 ExpiresByType audio/ogg                 "access plus 1 month"
 ExpiresByType video/mp4                 "access plus 1 month"
 ExpiresByType video/webm                "access plus 1 month"

 # HTC files  (css3pie)
 ExpiresByType text/x-component          "access plus 1 month"

 # Webfonts
 ExpiresByType application/x-font-ttf    "access plus 1 month"
 ExpiresByType font/opentype             "access plus 1 month"
 ExpiresByType application/x-font-woff   "access plus 1 month"
 ExpiresByType image/svg+xml             "access plus 1 month"
 ExpiresByType application/vnd.ms-fontobject "access plus 1 month"

 # CSS and JavaScript
 ExpiresByType text/css                  "access plus 1 year"
 ExpiresByType application/javascript    "access plus 1 year"

4. Fix broken links, preserve SEO

After we launched the new Anecka.com, a customer of PDF Press emailed me to let me know the link to PDF Press I had in the docs was broken. Sure enough my old link to www.anecka.com/pdf_press was giving me a 404 error page. Changing the URLs of the new site was out of the question and going to every site and every doc I had sent out would have been a nightmare. I needed some way to redirect users to the new PDF Press product page if they were using the old links. The solution was a simple redirect /pdf_press to /products/pdf_press.

    Redirect /pdf_press /products/pdf-press

5. Custom error pages

Custom error pages are a nice way to cushion a user’s experience if they click on a broken link or mistype a url. You can set custom error pages for different status codes:

     ErrorDocument 403 /error/error403.htm
     ErrorDocument 404 /error/error404.htm
     ErrorDocument 500 /error/error500.htm

6. Require SSL

Another thing you can do is force Secure Socket Layer (SSL) for your site.

     # require SSL
     SSLOptions +StrictRequire
     SSLRequire %{HTTP_HOST} eq "domain.tld"
     ErrorDocument 403 https://domain.tld

     # require SSL without mod_ssl
     RewriteCond %{HTTPS} !=on [NC]
     RewriteRule ^.*$ https://%{SERVER_NAME}%{REQUEST_URI} [R,L]

7. Setting Environment Variables

Setting environment variables can be accomplished using the “SetEnv” directive.

     SetEnv SPECIAL_PATH /foo/bin

You can then retrieve this variable using $_SERVER[‘SPECIAL_PATH’], you can even set this variable conditionally using the “SetEnvIf” directive. This is great if you need to set an ENV for your code based on the url:

     SetEnvIf HOST ^(www\.)?example\.com\.?(:80)?$    ENV=prod
     SetEnvIf HOST ^(stage\.)?example\.com\.?(:80)?$  ENV=stage
     SetEnvIf HOST ^(dev\.)?example\.com\.?(:80)?$    ENV=dev

8. Debugging Tools for .htaccess

Often you’ll need to test your .htaccess file before deploying to a live site. If you make a syntax error in your file it could cause an error on your site. To help debug your syntax you can use the following site: .htaccess check. Also you can debug your ReWrite conditions and rules using http://htaccess.madewithlove.be/.