Using 404 error pages correctly

Recently I changed the pages on my wife’s site Petals and Patches from .htm to .php. The site itself is working fine yet I was getting 404 errors when looking at CPanel. I really didn’t pay much attention to them until a few days ago when I realised that some people were of course still using the old .htm links.
I then discovered that my .htaccess needed updating. I thought I had done the updates correctly but have been informed that people are still getting generic 404 error pages.

My .htaccess file has the format (redirect /old htm new php)
e.g.
redirect /bags.htm http://www.petalsandpatches.com/bags.php
redirect /stitcheries.htm http://www.petalsandpatches.com/stitcheries.php

which does not seem to work.

I have a 404 error page at http://www.petalsandpatches.com/error-pages/404error.php which comes up when I type it in so that part works at least.
Typing in an old .htm url e.g. www.petalsandpatches.com/bags.htm gives a generic 404 page but not mine.
Obviously I have an error in my .htaccess file but cannot see it.
Can someone help me with what the error might be?

I have been doing some work on the .htaccess format and have discovered how to get the .htm now going to the 404 error page at least.
I just replaced redirect /bags.htm http://www.petalsandpatches.com/bags.php
with redirect bags.htm http://www.petalsandpatches.com/bags.php

But still wondering if possible to have .htm URLs go to .php without going through the 404 error?

How many pages are there in the site? Why not use 301 redirects to redirect the old URLs to the new ones?

There is about 30 pages on the site

Here is my .htaccess file

redirect stitcheries.htm http://www.petalsandpatches.com/stitcheries.php
redirect pincushions.htm http://www.petalsandpatches.com/pincushions.php
redirect ordering.htm http://www.petalsandpatches.com/ordering.php
redirect quilts.htm http://www.petalsandpatches.com/quilts.php
redirect applique.htm http://www.petalsandpatches.com/applique.htm
redirect chalkboards.htm http://www.petalsandpatches.com/chalkboards.php
redirect accessories.htm http://www.petalsandpatches.com/accessories.php
redirect seasidemoments.htm http://www.petalsandpatches.com/seasidemoments.php
redirect links.htm http://www.petalsandpatches.com/links.php
redirect bags.htm http://www.petalsandpatches.com/bags.php
redirect bears.htm http://www.petalsandpatches.com/bears.php
redirect stockisys.htm http://www.petalsandpatches.com/stockists.php
redirect clothdolls.htm http://www.petalsandpatches.com/clothdolls.php
redirect index.htm http://www.petalsandpatches.com/index.php
redirect blockofthemonth http://www.petalsandpatches.com/blockofthemonth.php
redirect onfreedomswings.htm http://www.petalsandpatches.com/onfreedomswings.php
redirect naturesgifts.htm http://www.petalsandpatches.com/naturesgifts.php
redirect orderform.htm http://www.petalsandpatches.com/orderform.pdf
redirect bears_viewcart.htm http://www.petalsandpatches.com/bears.php

Redirect 301 /stitcheries.htm http://www.petalsandpatches.com/stitcheries.php

So something in this format?

I am not certain of your question?

Do you mean I need to add the term 301 into each line?

Yes. You need to add the 301 to indicate that this is a permanent redirect, so Google and others can update their records accordingly.

If the domain hasn’t changed, then you can just use

Redirect 301 /index.html /index.php
Redirect 301 /contact.html /contact.php

or whatever; no need to use the full URL. (Although you can if you wish.)

I don’t know if this still holds true or also applies to Redirects

The {REQUEST_URI} string starts with a / character. Apache changed regex engines when it changed versions, so Apache version 1 requires the leading slash while Apache 2 forbids it! We can satisfy both versions by making the leading slash optional with the expression ^/? (? is the metacharacter for zero or one of the preceding character).

tiger,

Sorry to be a late comer to your thread but, as SitePoint’s former mod_rewrite guru, I rely on mod_rewrite:

RewriteEngine on RewriteCond %{DOCUMENT_ROOT}/$1.php -f RewriteRule ^([a-z]+).htm $1.php [R=301,L]

If your lowercase filename (requested with a .htm file extension) exists as a .php script, redirect to the filename.php script. The $1 in the RewriteCond is a backreference to the atom created in the RewriteRule and is used to extract the filename without the .htm extension for Apache to check whether the .php version exists before making a redirection to the land of 404. The %{DOCUMENT_ROOT} is used because the -f normally operates on the %{REQUEST_FILENAME} which provides the server’s path to the file.

You might benefit from reading my mod_rewrite tutorial as it contains explanations and sample code. It’s helped may members and should help you, too.

Regards,

DK

1 Like

Sorry - I missed this part of your question earlier.

To use a custom error page, you need to add this to your .htaccess:

ErrorDocument 404 /404error.php

tiger,

TB is quite correct as that is the syntax for ErrorDocument handling by Apache.

Apache also has a little-used module which can correct a limited number of typos and capitalization errors: mod_speling (their spelling error is said to be intentional - an inside joke). IMHO, this is a pretty user-friendly module to be using.

IMHO, mod_rewrite can also be used to send the errant request to an error handling script and include the original request to help the handler redirect to either your sitemap or a similar page.

AT THE END OF YOUR mod_REWRITE code:

# Prior code should have already performed a redirection to a file (or a directory) RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule .? error_handler.php?request=%{REQUEST_URI} [L]

This snippet checks whether the request is a file or a directory and, if neither, redirects to the error_handler script with the request in the $_GET array. What you do with that is a mark of your webmaster skills but could include a brief message and a timed redirection to your sitemap up to changing to request to lowercase and then parsing it for key words before making a redirection to the closest key word (else to the sitemap).

Edit: If you are concerned about a prior redirection changing {REQUEST_URI} and want to use {THE_REQUEST} instead (in the RewriteRule), feel free to change the Apache variable used in the redirection.

IMHO, be kind to your visitors but without going overboard (i.e., don’t waste too much effort “handholding”) will help visitors to your website. Use whichever technique best suits your temperament and website.

Regards,

DK

Thank you all for your help and advice. thus far it has been very useful.
Excuse my obtuseness but I an struggling with the difference between the following snippets

Redirect 301 /index.html /index.php

and

Redirect 301 index.html index.php

I have the .htaccess file in the same directory as the (old) .htm and the .php.
Does the presence of the leading / affect the operation of flow of code?

Hi Tigers,

Nothing obtuse about that as it’s a very valid question. The answer is that the first slash PROBABLY isn’t required but the second slash is required to make it an (internal) absolute redirection. That’s simply the required syntax for the Redirect (mod_alias) directive.

Regards,

DK

Still have some puzzlement concerned how the 301 redirect works or perhaps how I think it works.
I have assumed that the code fragment below

 redirect 301 stitcheries.htm http://www.petalsandpatches.com/stitcheries.php

would redirect stitcheries.htm to stitcheries.php.
It seems however that it actually sends the user to my custom 404 error page, which is good in a way as it means that users stay on the site. When they select the given home button it takes them to index.php.

Is that the way the 301 works viz. to an error page rather than straight to the newer page?

Unless of course I have still missing something or done something incorrect?

I believe the correct form is with a capital:

Redirect 301 /stitcheries.htm http://www.petalsandpatches.com/stitcheries.php

Linux/Unix are case sensitive, so I’m guessing redirect 301 will not work. When functioning correctly, it will redirect the old page to the new, not produce a 404 error.

I would always include the leading / in the file path. (It indicates the root directory.) @dklynn - who knows vastly more about this stuff than I do - thinks it’s optional, and if you can get it working without, then fine. But if it still doesn’t work once you’ve capitalised Redirect, that would be my next suggestion to try.

Tigers,

You appear to be jumping around between mod_rewrite and mod_alias for your redirection. Only one is required and mod_alias will always take precedence (because it is part of the Apache core) over mod_rewrite.

Thanks, TB, for the vote of confidence … despite my error with the leading slash for the URL-path!

From https://httpd.apache.org/docs/2.4/mod/mod_alias.html#redirect:

Redirect Directive

Description: Sends an external redirect asking the client to fetch a different URL
Syntax: Redirect [status] URL-path URL
Context: server config, virtual host, directory, .htaccess
Override: FileInfo
Status: Base
Module: mod_alias
The Redirect directive maps an old URL into a new one by asking the client to refetch the resource at the new location.

The old URL-path is a case-sensitive (%-decoded) path beginning with a slash {my bad!}. A relative path is not allowed.

The new URL may be either an absolute URL beginning with a scheme and hostname, or a URL-path beginning with a slash. In this latter case the scheme and hostname of the current server will be added.

Then any request beginning with URL-Path will return a redirect request to the client at the location of the target URL

However, I believe that Apache is kind enough to convert capitalization errors so they don’t effect the directive, in other words, “Redirect” will be seen when “redirect” is requested. The same, however, is NOT true for the case-sensitive URL-path or the case-sensitive URL!

If you will show your entire .htaccess code, I’m sure we can spot the conflict which is causing the redirection to your 404 script.

Regards,

DK

Here is the .htaccess as requested

# Added redirections from .htm to .php pages
Redirect 301 stitcheries.htm http://www.petalsandpatches.com/stitcheries.php
Redirect 301 pincushions.htm http://www.petalsandpatches.com/pincushions.php
Redirect 301 ordering.htm http://www.petalsandpatches.com/ordering.php
Redirect 301 quilts.htm http://www.petalsandpatches.com/quilts.php
Redirect 301 applique.htm http://www.petalsandpatches.com/applique.htm
Redirect 301 chalkboards.htm http://www.petalsandpatches.com/chalkboards.php
Redirect 301 accessories.htm http://www.petalsandpatches.com/accessories.php
Redirect 301 seasidemoments.htm http://www.petalsandpatches.com/seasidemoments.php
Redirect 301 links.htm http://www.petalsandpatches.com/links.php
Redirect 301 bags.htm http://www.petalsandpatches.com/bags.php
Redirect 301 bears.htm http://www.petalsandpatches.com/bears.php
Redirect 301 stockisys.htm http://www.petalsandpatches.com/stockists.php
Redirect 301 clothdolls.htm http://www.petalsandpatches.com/clothdolls.php
Redirect 301 index.htm http://www.petalsandpatches.com/index.php
Redirect 301 blockofthemonth http://www.petalsandpatches.com/blockofthemonth.php
Redirect 301 onfreedomswings.htm http://www.petalsandpatches.com/onfreedomswings.php
Redirect 301 naturesgifts.htm http://www.petalsandpatches.com/naturesgifts.php
Redirect 301 orderform.htm http://www.petalsandpatches.com/orderform.pdf
Redirect 301 bears_viewcart.htm http://www.petalsandpatches.com/bears.php

Well, I think we’ve now established that you do, indeed, need the leading / on the old filepath, so I would start by changing that.