On Apache servers, you put many configuration settings in your .htaccess file.

Syntax Errors in your .htaccess file will crash your entire site. If you have errors in your /public_html folder .htaccess, you will crash all sites set up as sub-domains or parked domains as well.

This post is not a tutorial on modifying .htaccess files, but on how to test a complex command outside of your main site.

There are many techniques for identifying which line is the one crashing your site. Your site error log may say a certain command is not allowed in your .htaccess (your hosting provider may have to make the setting change for you). Or you restore a version that you know worked, test it (make sure it still works), and add small chunks of the bad file: works to line 57, crashes by line 100, works to line 70, crashes by line 85, works to 75, crashes by 80, ah it’s line 77. (When narrowing down which chunks work, make sure you keep section tags matched, having unmatched .htaccess section tags will definitely crash your site.)

Testing Syntax Outside Your Main Site

Your site is functioning. You want to add something to .htaccess, without crashing the site.

Before you do anything else, Back Up to a new folder on your computer (very deliberately Not to the folder you use every day for web site work!) your functioning .htaccess file. Then rename it in this special folder, with date and status, and make it a .txt file). Keep calm, keep sane, be clear. Have a working version you can fall back on. Keep your working version safe.

Test the new command first, before adding it to your main site, someplace with no effect to normal site visitors.

You could have a .htaccess file in any folder. The .htaccess from the root folder is read first, then any .htaccess files in sub-folders to get to the folder a web page is in. (Don’t replicate all the commands from the root .htaccess, and don’t make a .htaccess in each folder unless you need a change from the folders above, that just slows down your web site.)

Make a new folder, a sub-folder of your main site. Any made-up valid folder name. Put a minimal HTML file in that folder. Here’s an example:

    Minimal HTML file

This is a Minimal HTML file for Testing.

Test that this page displays in your web browser.

Now put a new, empty .htaccess file in this new folder. (The file name must start with a period, so it may be easiest to use your FTP program to create a new file on the server, and then use your FTP program to open it for editing; most Windows programs don’t understand file names starting with a period…)

Put a comment (any line that starts with a # is a comment) in this .htaccess file, save it, make sure the test page still displays.

Now you can begin actual testing of the line that was causing all the trouble.

In the following example, start with a very simple statement, gradually add a piece at a time and make it work.

Each line of the example below was how I tested a long User-Agent. Below is the final result, with the bad lines commented out.

This one works:

SetEnvIfNoCase User-Agent LinkedInBot itWorked

This has a slight change, the parenthesis, and fails:

SetEnvIfNoCase User-Agent LinkedInBot(compatible itFailed

The failure is a 500 Server Error. (Ignore the itWorked or itFailed environment variables being set, that’s not what the failure is, the failure is an illegal use of a special character in the statement.)
Change to this and it works again:

SetEnvIfNoCase User-Agent LinkedInBot\(compatible itWorked

The backslash converts the meaning of the opening parenthesis from special character to something to display. (Parentheses enclose partial results that can then be referred to, and the missing closing parenthesis makes the syntax invalid, 500 Error.)

Then add a single line of code and test it (in order to test the bad lines below, you’ll have to remove the leading #… as a comment, of course it’s valid!)

Notice the difference between each line and the one before it.

Working Example: Testing for a User Agent

Ignore the word wrapping of long lines, on this screen and in your text editor. Each command must be on a single line (i.e. the command ends when you press the Enter key). Don’t type line numbers, displayed here only to help you see what is a separate line.

# actual user agent string:  LinkedInBot/1.0 (compatible; Mozilla/5.0; Jakarta Commons-HttpClient/3.1 +http://www.linkedin.com) 

# .htaccess lines that start with # are comments. Comments can Only start at the beginning of a line.

# If the User-Agent system variable contains the value "LinkedInBot" (not case sensitive), set an environment variable "itWorked":
SetEnvIfNoCase User-Agent LinkedInBot itWorked

# SetEnvIfNoCase User-Agent LinkedInBot(compatible itFailed
SetEnvIfNoCase User-Agent LinkedInBot\ \(compatible itWorked
# must escape an open parenthesis ( by preceding it with a back-slash \
# must escape a space meant as part of the string (so it isn't separating parameters)

SetEnvIfNoCase User-Agent LinkedInBot/1\ \(compatible itWorked
# a forward slash / is okay

# SetEnvIfNoCase User-Agent LinkedInBot/1.0\ \(compatible itFailed
SetEnvIfNoCase User-Agent LinkedInBot/1\.0\ \(compatible itWorked
# must escape a period .

SetEnvIfNoCase User-Agent LinkedInBot/1\.0\ \(compatible;\ Mozilla/5 itWorked
# semicolon ; is okay
SetEnvIfNoCase User-Agent LinkedInBot/1\.0\ \(compatible;\ Mozilla/5\.0; itWorked
SetEnvIfNoCase User-Agent LinkedInBot/1\.0\ \(compatible;\ Mozilla/5\.0;\ Jakarta\ Commons itWorked
SetEnvIfNoCase User-Agent LinkedInBot/1\.0\ \(compatible;\ Mozilla/5\.0;\ Jakarta\ Commons- itWorked
# hyphen - is okay (test if it works when could be part of a character range e.g. a-f)

SetEnvIfNoCase User-Agent LinkedInBot/1\.0\ \(compatible;\ Mozilla/5\.0;\ Jakarta\ Commons-HttpClient/3\.1  itWorked
SetEnvIfNoCase User-Agent LinkedInBot/1\.0\ \(compatible;\ Mozilla/5\.0;\ Jakarta\ Commons-HttpClient/3\.1\ +http  itWorked
# plus + is okay

SetEnvIfNoCase User-Agent LinkedInBot/1\.0\ \(compatible;\ Mozilla/5\.0;\ Jakarta\ Commons-HttpClient/3\.1\ +http://www  itWorked
# colon slashes :// are okay

SetEnvIfNoCase User-Agent LinkedInBot/1\.0\ \(compatible;\ Mozilla/5\.0;\ Jakarta\ Commons-HttpClient/3\.1\ +http://www\.linkedin\.com  itWorked
SetEnvIfNoCase User-Agent LinkedInBot/1\.0\ \(compatible;\ Mozilla/5\.0;\ Jakarta\ Commons-HttpClient/3\.1\ +http://www\.linkedin\.com)  itWorked
# closing parenthesis (at least when isn't an open parenthesis it could match) is okay