Posts Tagged ‘.htaccess’

Compressing HTML and PHP files on 1and1

Friday, July 9th, 2010

1and1 doesn’t have mod_deflate or mod_gzip enabled on its home or business shared server packages which means that many of the usual .htaccess tweaks to compress your web pages won’t work. Here’s something very simple tweaks that will work with 1and1, and with other hosts too.

Set up your .htm and .html files so that they are parsed by the PHP interpreter by adding this one line to your .htaccess file.

AddType x-mapp-php5 .html .htm

Then create and upload a php.ini file to your websites root directory. If you are using WordPress then this should be the same directory as the one where wp-config.php is.

The contents of the php.ini should be as follows.

zlib.output_compression = On

This line causes PHP files to be served as compressed if the browser supports it. And as we have registered .html and .htm as being PHP files they will now be compressed.

You can test that the HTTP compression is turned on by using this simple HTTP compression checking tool, or by using the more comprehensive Page Speed add-on for Firefox from Google.

Here are the results from the HTTP compression checking tool showing that compression is now on, and that the home page HTML is being served using 76% less data. Note that this saving refers only to the HTML page, and not to any other images, style sheets, or JavaScript.

rml gzipped on 1and1

Increasing expiry time of images on 1and1

Another quick tweak you can make to your .htaccess is to increase the expiry time of your images, and other data files. This will result in quicker loading times for regular visitors as the files will stay in their browsers cache for longer.

Add this to your .htaccess. You can increase the expiry times if you don’t think those files will change.

#Increase cache time for resources

ExpiresActive On
ExpiresByType image/gif "access plus 2 weeks"
ExpiresByType image/jpeg "access plus 2 weeks"
ExpiresByType image/png "access plus 2 weeks"
ExpiresByType image/ico "access plus 2 weeks"
ExpiresByType text/css "access plus 2 weeks"
ExpiresByType text/javascript "access plus 2 weeks"
ExpiresByType application/x-javascript "access plus 2 weeks"

Use Google’s Page Speed add-on to verify that this has worked. Go to the Resources tab to see the headers for each individual file served from the HTTP server. Below you can see the current date/time, and that the expiry time is set two weeks into the future.

expires date for image

Caching and expiry changes combined

Here are before and after results for Google’s Page Speed tool of applying both the above changes to another of my websites. You can see that these quick changes give the website a small increase in score.

website score before

From 88 to 92.

website score after

This isn’t a big jump, but it may make a difference. I highly recommend you look at the other performance recommendations from the Page Speed tool, as it can give you loads of ideas for how to make your site faster and more responsive.

Redirect all but selected sub-directories using .htaccess rules

Friday, July 2nd, 2010

I have an old website which is almost defunct, and I wanted to redirect all the traffic from it to my new website – APART from a few selected directories. This is how I managed to get the redirects working using a .htaccess file.

For this example the directory containing the material that I don’t want to redirect is called ‘goodstuff’. The RewriteCond conditions are setting up the excluded directories (the exclamation mark means ‘not’).

RewriteEngine on
RewriteCond %{REQUEST_URI} !^/goodstuff/.*
RewriteCond %{REQUEST_URI} !^/goodstuff$
RewriteRule .* [R=301,L]

The reason I have two RewriteCond lines is because the web address could either be written with the trailing slash or without. E.g. goodstuff/ and goodstuff are the same, but I use two lines to cope with both cases.

The first RewriteCond matches all files and folders within this directory. The second is only matching the directory name without the trailing slash added.

The RewriteRule is telling the web server where to redirect the traffic to. The traffic is being redirected permanently (301 code), and the L states that this is the final rule for anything that matches our conditions.

Here’s another way of doing it which works, but it isn’t as precise. It redirects all addresses which start with ‘goodstuff’. This means it would match all the files that the first example matched. But it could match others as well.

RewriteEngine on
RewriteCond %{REQUEST_URI} !^/goodstuff.*
RewriteRule .* [R=301,L] 

As well as matching a /goodstuff and /goodstuff/ directory, it could also match a /goodstuffhere/ directory, and a /goodstufffile.html.

Upgrade WordPress to 2.8.1 on 1and1

Tuesday, July 14th, 2009

In the bad old days upgrading anything WordPress related (plugins, themes, or WordPress itself) would at best involve manually downloading a zip, extracting it locally and then using FTP to upload the changes to your web server. At worst it could require manually editing files, and making database changes.

In February last year I wrote about how cool it was that the All in One SEO Plugin had a one-click upgrade facility. Updating plugins had always been a big pain, especially when you have a blog with many plugins (this one has about 10) so it was great when WordPress introduced one-click plugin upgrade support. Although plugins could now be upgraded with a single click, upgrading WordPress itself was still a manual task.

In WordPress 2.7 they introduced one click upgrade support of WordPress itself. When 2.8.0 was released a message at the top of my blog console prompted me to do a one-click upgrade. I decided to wait. Upgrading to a x.x.0 release can be risky. These are major updates and often have many bugs. Waiting until the x.x.1 release can be safer unless there is an urgent reason to upgrade (such as a critical security update).

Another reason for delaying a WordPress upgrade is that it can take a while for the plugins that you use to be updated to be compatible with the new version. Sometime no changes are needed, but when WordPress update their database structure, plugins are particularly vulnerable to breaking.

Even though you can now upgrade from 2.7.x to 2.8.x with one click, upgrading is never that simple. With each upgrade there is a chance that you will completely trash your blog.

Firstly make sure you have plenty of time. If it goes well it shouldn’t take too long. What you don’t want to do is for it to go badly wrong and end up with your blog trashed, just before you have to leave for an urgent appointment.

You MUST do your backups before upgrading. Before backing up I make sure all the plugins are up-to-date and I delete any comment spam so this isn’t backed-up.

I always do three different backups.

  1. File backup – I FTP all the blog files down to my computer.
  2. XML export – Export all the blog information as an XML file using the Tools->Export option.
  3. MySQL database backup – A full MySQL database backup using the backup instructions from the official WordPress website. On 1and1 you select the MySQL admin panel using the highlighted button shown below.

Oneandone MySQL icon

After backing up I verify that the backups look correct. I generally diff the XML and database dump to my previous backup using the Beyond Compare tool. The main thing to check is that the backups haven’t been truncated due to a failed download. If the files are much smaller than previous backups then you may have a problem.

I’d read that in order for the upgrade to work on 1and1 you need to ensure that your website is processing .php files using PHP5 rather than PHP4. To ensure this you must have the below line in your .htaccess file in the root of your blog.

AddType x-mapp-php5 .php

After all this there was just one thing left – to press the ‘Upgrade’ button.

I pressed it and held my breath. Some messages appeared on the screen and about 10-15 seconds later it said the upgrade had succeeded. At first I thought something must have gone wrong, as it was so quick. I logged back into the blog and saw that it had worked!

The only problem that I found was due to me having made some changes to the default theme. These changes had been overwritten. Luckily due to the file backup that I had made by FTP I was able to restore them in a few minutes. The lesson to learn here is not to change the default theme. You should copy it to a new directory and only change the copied version. If you want to keep any updates to the default theme in sync with your modified theme you may have to manually merge them in, but at least you won’t lose your theme updates.

Congratulations to the implementers of this feature in WordPress. It is much appreciated by me :)

Using a common form mail script for multiple websites

Thursday, June 12th, 2008

I run a number of different websites. Most of them have a contact page which is powered by a form mail script. Until recently each of these websites used an almost identical copy of the same form mail script – I use PHPFormMail but you could adapt this solution for other form mail scripts. Each contact us page has very similar HTML in it. I wanted a way of sharing a common form script and wanted to avoid the duplicated HTML without losing the individual styling of each contact us page.

For this to work for you you’ll need:

  1. All your websites to be on a single host. The code on this page is what I used on my 1and1 hosting account, but the solution should be similar for other web hosts.
  2. To be allowed to use .htaccess files.
  3. Have enough technical knowledge to understand what I’m saying and to customise this for your own site. I’ll give you enough information to implement this, but only if you have enough understanding of knowledge of HTML, PHP and .htaccess files.

On my web server I use one directory for each domain. I map my domain names to directories like this:    ->   /advancedhtml-web/    ->   /reviewmylife-web/ ->   /interrail-web/

You’ll note that it is not possible to access the root of my web hosting account ‘/’ from the web.

I’ve added a common directory to store the form mail script and the form HTML. This directory is not accessible from any web address. I’ll explain the contents of the later on.


The formmail.php is my usual PHPFormMail script.

I then set up a global variable in a .htaccess file in the root of my web server. This .htaccess file is not accessible to any of my website visitors but it is processed.

The contents of the .htaccess look like the below snippet. You’ll need to replace the /kunden… part with the path of your own common directory.

SetEnv COMMON_PATH /kunden/homepages/25/dxxxxxxx/htdocs/common

If you don’t know what your web server path looks like create a file called ‘test.php’ with the following contents – <?PHP phpinfo(); ?> and then load file from your browser. You can use this test.php to verify that your new environmental variable is present. Below is my
<form method="post" action="commonformmail.php">
<table width="80%" cellpadding="0" cellspacing="0">
  <td><font face="arial">Name</font></td>
  <td><p><input type="text" name="name"></p></td>
  <td><font face="arial">Email</font></td>
  <td><p><input type="text" name="email"></p></td>
  <td><font face="arial">Subject</font></td>
  <td><p><input type="text" name="subject"></p></td>
  <td><font face="arial">Message</font></td>
  <td><p><textarea name="message" rows="15" cols="45"></textarea></p></td>
  <td><p><input type="submit" name="Submit" value="Send"></p></td>
<input type="hidden" name="redirect" value="thanks.htm"></p>
<input type="hidden" name="recipient" value="commonmail">
print "<input type="hidden" name="referer" value="" . $_SERVER["SERVER_NAME"].$_SERVER["REQUEST_URI"] . "">n";
<input type="hidden" name="env_report"

Look at the PHPFormMail documentation for information about the redirect, recipient and env_report fields. You’ll note that I have added a referer field so that I’ll know which of my websites this form was posted from. The value of the recipient field has to be present in the PHPFormMail $recipient_array. If your contact page is a .html rather than a .php you’ll have to make sure that you can use PHP in HTML files.

In your contact us/email HTML file you can include the form like this:

include_once($_SERVER['REDIRECT_COMMON_PATH'] . '/');

The final part of the solution is to add a commonformmail.php to each of your individual website directories. It will look like this and just includes the shared form mail script.

include_once($_SERVER['REDIRECT_COMMON_PATH'] . '/formmail.php');

From now on you can change the behaviour and look of all your website forms from one place.

Custom error pages on 1and1 when HTML files are set as PHP types

Monday, May 26th, 2008

A long time ago I set up custom error pages on my 1&1 hosted websites. However recently I noticed that they had stopped working. When a 404 error occured, instead of redirecting to my error page I got an advert filled parking page.

1and1 error page

I re-checked their instructions for setting up the error pages on their FAQ and I was pretty sure that I was setting the pages up correctly.

After spending over an hour trying to figure out what was going wrong I stumbled on the ‘Empty Parking Pages’ link on the Domain Overview in their Administration control panel. You can see the position of this link in the red box.

1and1 admin page

On this page is the option to turn off their ‘Empty Parking Pages’. I turned this option off – it then took a few minutes for the change to be visible on my website.

1and1 empty pages parking

Part of the message says:

When using this service, a page from our webserver will be displayed instead. Unless, of course, you have set up your own error message.

Now instead of getting the advert filled parking page I got a plain:

Error 404 – Not found
Your browser can’t find the document corresponding to the URL you typed in.

It is better than before but it is still not my error message!

It seemed the only way I could get correctly working error files is to create files with the following file names in your site’s root directory – ‘error400.html’, ‘error403.html’, ‘error404.html’ and ‘error500.html’. No entry in the .htaccess file is needed – 1&1 automatically picks these files up as your error pages.

So why weren’t the ErrorDocument lines in my .htaccess working?

In my .htaccess file I also have the following line:
AddType x-mapp-php4 .html .htm

This line allows PHP code to be processed from .htm and .html files. If I remove this line then my ErrorDocument lines start working. It therefore seems that 1and1 have configured their servers so that you can only errors generated when you try to access static pages will cause the ErrorDocument directive to be used. Usually .html and .htm are static, however my AddType line in the .htaccess changed them into dynamic pages.

I removed .html from the AddType line. After doing this the ErrorDocument worked for .html files but not for .htm.

After all this I have deduced the following:

  1. If you want to get rid of the advert filled parking pages you need to use the control panel.
  2. If you configure your 1&1 .htaccess file to allow PHP in .htm and .html then the ErrorDocument line won’t work for any missing .htm or .html files. However the ErrorDocument will work for non-PHP files types.
  3. The ErrorDocument directive will never work for .php file types as these are always registered as being PHP types.
  4. The only way to get working error files for all types of errors is to create ‘error400.html’, ‘error403.html’, ‘error404.html’ and ‘error500.html’ files.

Final tip

In the 1&1 FAQ on creating error pages they give three suggestion for creating custom error pages:

  1. Using ErrorDocument in .htaccess (which only works for static document types).
  2. Adding the errorXXX.html error pages (which does work for all document types).
  3. Adding the below code to your .htaccess.

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) /errordocument.html

I would suggest that you don’t add this to your .htaccess! This redirects any 404 ‘not found’ errors to the errordocument.html webpage. This causes a 200 error code to be returned rather than a 404 error code. This is a bad idea as it could cause search engines to end up indexing all the error pages on your website.