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.
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]
</IfModule>
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} 208.96.122.142 [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!
Gzip:
<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
</IfModule>
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"
</IfModule>
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
SSLRequireSSL
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/.