May the source be with you, but remember the KISS principle ;-)
Home Switchboard Unix Administration Red Hat TCP/IP Networks Neoliberalism Toxic Managers
(slightly skeptical) Educational society promoting "Back to basics" movement against IT overcomplexity and  bastardization of classic Unix

Apache mod rewrite

News Apache Security Recommended Books Recommended Links Flags
mod rewrite mod_security Apache .htaccess file Using deny directive in apache .htaccess Blocking bad referrers
RewriteBase directive Perl Regular expressions Tips Humor Etc


Module mod-rewrite actually implements a simple production type expert system. It has some interesting features and supports Perl-style regular expressions.

It operates using set of variable that come from three sources:

To use any of the variables from that long list, you wrap the variable name in curly braces, and prefix with a percent sign. for example


Module mod_rewrite is probably the most important, the most well known and the most successful Apache module. It can be called the Swiss Army knife of Apache modules. 

In addition to sophisticated rule-based URL-rewriting based on Perl-compatible regular expressions, mod_rewrite gives you the ability to keep query-string input safe, keep your site search-engine-friendly, make your URLs user-friendly, retain “old” URLs after a restructuring, and stop hot linking. 

Rules of the game

There are two types of rules the mode operates with two types of rules RewriteRule and RewriteCond. 

RewriteRule is fundamental, main type of rules. It can be prefixed by one or several RewriteCond rules.

The latter can't exist by themselves and set of  RewriteCond rules should always end with  RewriteRule

Chaining of RewriteCond rules by default is performed using AND logical condition.

But it can be overwritten by specified OR - The OR flag which allows you to combine rewrite conditions with a logical OR relationship as opposed to the default AND.

You can also specify case sensitive or case insensitive matching: NC - The No Case flag tells Apache to ignore the case of the string in the regex and is often necessary when writing a RewriteCond statement that matches the {HTTP_HOST} variable for a domain name, which is not case sensitive.

Behaviors of RewriteRule is controlled by so called flags. Among them

Due to the this complex chaining of rules you can create "forever" loops in mod rewrite rule sets. In this case it will execute the loop predetermined set of times (let's say 100) and then exit with code 500.


Module mod_rewrite provides configuration directives that can provide a wide range of rewriting.

Left side of the rule operates with URL, the same value as %{REQUEST_URI%}.

For example, you might have recently replaced an older section of your website with a newer more up-to-date version, with a different URL. To automatically redirect any URL in the old structure to the index in the new location, you might use something similar to this:

RewriteEngine On
# Rewrite requests for the old directory to the new index
RewriteRule \,org/(.+)$ \.info/$1 [R,NC,L]
This rule tells Apache to respond to all requests to any file in the .org site with the file in the  .info/ site. The flags at the end specify to redirect to the new URL, ignore case when matching, and to stop processing any other rules that might match the requested URL See flags.

Same can be done for level two directories

RewriteEngine On
# Rewrite requests for the old directory to the new index
RewriteRule /News/(.+)$ /Bulletin/$1 [R,NC,L]

mod_rewrite can intercepts the request and translate it into the query string–appended PHP request, which is then parsed through the PHP engine. Another thing to keep in mind: if the preceding directory actually does exist and the RewriteRule shown here is active, Apache will still completely ignore the real path and proceed as planned with its URL rewriting.

In order to use mod_rewrite, you have to inform Apache that you want to enable the module in the given configuration zone — a .htaccess file, or a <Directory> section in http.conf.

RewriteEngine takes either On or Off as its value. The next key line is simply a regular expression used to match an incoming URL, and the new URL to use in its place:

# Rewrite /category/item/ to catalog.php?... 
RewriteRule ^(\w+)/(\w+)/?$ catalog.php?cat=$1&item=$2

The pattern looks for a two-level directory request, using the \w pattern to match only valid “word” characters for each directory. Then, it uses the values of each of the two directories as the category and item number for the PHP script.  PCRE syntax used and  $-prefixed backreferences refer to submatches in the original pattern.

Backreferences are a simple way to include a sub-match from the previous pattern directly in the substitution string. Looking again at the rule:

# Rewrite /category/item/ to catalog.php 
RewriteRule ^(\w+)/(\w+)/?$ catalog.php?cat=$1&item=$2

There are exactly two submatches defined in the regular expression matched against the URL: both of the “word”-character groupings, indicating directories. In the substition string, the backreferences $1 and $2 are used to automatically include the value of the first and second sub-matches, correspondingly.

Backreferences simply start counting at 1, which corresponds to the first submatch.

You can actually use it as a rudimentary type-checking layer. In some situations, you might be pulling a number from a query string variable, a page number or item number for example. If you want to make absolutely sure it’s a number you’re using, and not something potentially more evil—like a SQL injection attack—you have two options.

The first and most commonly used method is adding extra code to your PHP scripts to actually check if the $_GET parameter indeed holds a number. For example, you might have the URL: 

URLs such as this are often found in paginated content, usually in page-navigation links. Somewhere in the code that loads the specified page of the article, you might see the following:

if (isset($_GET[‘page’]) and is_numeric($_GET[‘page’])) { $page = $_GET[‘page’]; } else { $page = 1; } 
// And so on.... 

The previous code simply checks first for the existence of a specific $_GET value, in this case ‘page’, and then checks if the value passed is indeed a number—if not, a default value of one is assigned.

Such type-checking is a good idea, and helps shield your PHP scripts from nasty script kiddies who want to break your website. Unfortunately, it can become somewhat tedious requiring your PHP scripts to check whether or not the value was set, and if it was indeed a number. Using mod_rewrite, you can eliminate the type checking from your PHP code—all you have to do is ensure the pattern matches only numeric values:

# Ensure only numeric values for the page

RewriteRule ^article/([0-9]+)/? article.php?page=$1
RewriteRule ^article/[^0-9]+/? article.php?page=1
The first RewriteRule checks for any valid URLs in the form of /article/page/, and translates the given request into the call to the PHP script. The second RewriteRule is set up to catch all malformed URLs calling for an article, but giving an invalid value for the page number. Any such request is automatically assigned the first page in the article.

There are two things to note in the previous set of RewriteRules. First, both rules are processed in order; processing does not stop at the first rule, but continues through all rules given. Second, the redirection to the article.php script is handled internally—no HTTP redirect/moved status code is sent to the client at all. In order to alter these default behaviors, you can use a set of flags at the end of each rule.

RewriteRule Flags

mod_rewrite uses "flags" to give our rewrite conditions and rules additional features. We add flags at the end of a condition or rule using square brackets, and separate multiple flags with a comma. The main flags with which you'll need to be familiar are:

In order to control the ways that mod_rewrite handles and processes each RewriteRule, you have a set of 15 different flags that you can add following each rule. Flags are contained within brackets, and multiple flags can be provided in a comma-separated list—all within a common set of brackets.

For example:

# Rewrite /category/item/ to catalog.php
RewriteRule ^(\w+)/(\w+)/?$ catalog.php?cat=$1&item=$2 [NC,R,L]

nocase|NC Similar to the i flag in PHP’s PCRE syntax, the nocase flag makes the pattern case-insensitive. For example, the following two patterns are identical:

RewriteRule ^([A-za-z])/? catalog.php?cat=$1
RewriteRule ^([a-z])/? catalog.php?cat=$1 [NC]
Normally mod_rewrite uses an internal Apache redirect when rewriting URLs, and this redirection is invisible to the user. If instead you wanted to do a formal redirect, complete with HTTP status code, you can use the redirect or R flag.

By default, the redirect flag sends a HTTP 302 Moved Temporarily code, such as in the following rule:

RewriteRule ^article/(\d+)/? article.php?page=$1 [R]
If you wanted to change the status code to a HTTP 301 Moved Permanently, or any other status code between 300 and 400, you simply add the code to the end of the redirect flag:
RewriteRule ^article/(\d+)/? article.php?page=$1 [R=301]
Similar to the redirect flag, using the forbidden flag immediately sends a HTTP 403 Forbidden response to the client. Whenever both a redirect flag and forbidden flag are present for the same rule, the forbidden flag will have priority (the redirect will be ignored, 403 sent).

gone|G Another HTTP status code control flag, gone, sends a response of HTTP 410 Gone, to inform the client the page no longer exits. When combined, the gone flag has precedence over the redirect flag, but not the forbidden flag.

last|L To stop the processing of RewriteRules after a successful match is found, you use the last flag. In the previous example dealing with processing article page numbers, the rule processing would still continue to the second rule (but not find a match), even if the first rule was a successful match. To stop the processing after the first rule matched, you could simply use the last flag: RewriteEngine On

# Ensure only numeric values for the page
RewriteRule ^article/([0-9]+)/? article.php?page=$1 [L]
RewriteRule ^article/[^0-9]+/? article.php?page=1 [L]
The next flag restarts the rewriting process at the beginning of the rule list. When the rules are re-processed, the URL matched is not the original request from the client, but the internally rewritten URL at the point where the next flag was used. For example:
RewriteRule ^article/(\d+)/? article.php?page=$1
RewriteRule ^catalog/(\w+)/? catalog.php?cat=$1 [N]
RewriteRule ^catalog/(\w+)/(\w+)/? catalog.php?cat=$1&item=$2
In this example, if a URL is called that matches the second rule, such as http://localhost/catalog/ stuff/, rewriting will stop processing at that point and automatically restart at the beginning of the rule set, using the new substituted URL, catalog.php?cat=stuff. The substituted URL is then itself filtered through the whole rule set.

Care should be taken when using the next flag, as infinite loops are possible.

chain|C If you wanted to treat a block of rules as a single related unit, similar to the try...catch syntax in PHP, you can use the chain flag. When using the chain flag, if a rule matches, the processing continues as expected and ignores the chain flag. If a rule does not match and a chain flag is present, all of the following rules that are chained together will be skipped as a whole block. For example, the following set of rules skips to the last rule if the first one does not match: RewriteRule ^article/(\d+)/? article.php?page=$1 [C] RewriteRule ^catalog/(\w+)/? catalog.php?cat=$1 [C] RewriteRule ^catalog/(\w+)/(\w+)/? catalog.php?cat=$1&item=$2 # Skip to this rule if any of the above don’t match RewriteRule ^article/[^\d]/? error.php

skip|S=number This flag allows you to skip the next number of rules when the current rule matches. While the behavior of the skip flag is similar to the chain flag, it behaves in exactly the opposite manner—skip jumps on a successful match; chain jumps on a failed match. type|T=mime-type If you want to override the MIME type sent for a document, you can use the type flag. For example, if you have a bunch of .xhtml files you want to serve up using a proper XHTML MIME type, instead of text/HTML, you could use the following:

RewriteRule ^.+\.xhtml$ - [T=application/xhtml+xml]
The cookie flag, as you might infer, sets a cookie on the client’s browser. The three required fields — name, value, and domain—specify the name of the cookie, the value of the cookie, and the domain for which the cookie is set. The optional lifetime parameter represents the life of the cookie, in minutes.

The path parameter sets the path of the cookie. For example, if you wanted to set a cookie named prevvisit to signify a user has visited the home page before (and shouldn’t be bothered with splash screens), you could use this:

RewriteRule ^index\.php$ - [] env|E=var:value 

The env flag allows you to set an environment variable var to the value provided. The value can also contain regular expression backreferences ($N and %N) for more complex variable control. Multiple environment variables can be set in one group of flags—they just need to be comma-separated like the rest of the flag list. qsappend|QSA In most situations when you’ll use mod_rewrite, anything provided as a query-string to the original URL is dropped when you perform a rewrite. If you want to preserve that information instead of dropping it, you can use the qsappend flag.

When using this flag, the rewrite engine simply takes the original query string and appends it to any new query string provided in the rewrite. For example:

RewriteRule ^index\.php$ index.php?foo=bar [QSA] 

This rule would change the index.php file, using the URL index.php?moo=cow, to be index.php?foo=bar&moo=cow. In the event that a query-string parameter in the original URL shares the same name as a parameter in the RewriteRule, the original value takes precedence.

noescape|NE When mod_rewrite performs its transformations, it goes to great lengths to make sure special characters in the rewritten URL are escaped before performing any internal or external redirection. For example:

 rewriterule ^somedir/? index.php?page="foo\%3b" [r] 
Given this rule, Apache would redirect the /somedir/ directory as requested, and the $_GET value for page will be a “safe” escaped value of foo%3b—mod_rewrite has escaped the \%3b value instead of replacing it with its semicolon substitute. To tell mod_rewrite to avoid any automatic escaping, you use the noescape flag:
RewriteRule ^somedir/? index.php?page=foo\%3b [R,NE] 

Given this rule, the new value of the page query-string parameter will be foo;.

passthrough|PT Use the passthrough flag when you want to combine mod_rewrite with other Apache modules that provide similar URL-handling functionality, such as mod_alias. For example, if you wanted to rewrite /foo to point to /bar, and then use mod_alias to translate /bar to /baz, you might try the following: RewriteRule ^/foo /bar Alias /bar /baz Unfortunately, because of the way Apache handles URIs internally, it would not work as written.

To make it work, add the passthrough flag:

RewriteRule ^/foo /bar [PT]
Alias /bar /baz

A general rule of thumb is to use passthrough if you are using more than one URL translating module to process a file.

Use the nosubreq flag to force the rewrite engine to skip a rule if the request is actually an internal subrequest. When using PHP and Apache together, there are seldom situations when this flag is actually needed. There are, however, some CGI scripting instances where this flag comes into play. For more information, see the Apache manual section on RewriteRule:  .

proxy|P The proxy flag tells the rewrite engine to stop processing the rule-set immediately and force the request through the Apache proxy module, mod_proxy. With all this attention being given to RewriteRule, you might think that it’s the main force behind mod_rewrite. In reality, its best role is part of the dynamic duo that is RewriteRule and RewriteCond.


The RewriteCond directive behaves much like  if () statement: it tests a string against a pattern or condition. If the input matches the pattern or string, the RewriteRule immediately following the RewriteCond directive is processed. The general format for RewriteCond is as follows:
RewriteCond TestString CondPattern
TestString is the string you are evaluating, and CondPattern is the regular expression or comparison value to check against. 

Variables RewriteCond is used with

The most common way that RewriteCond is used is to match the input string against a regular expression, similar to RewriteRule. However, when you use RewriteCond, you have access to large number of variables, so your input string can be more complex than a simple filename match. 

Variables come from three sources:

HTTP Header variables

The following are common  HTTP Header variables:

Web Server variables

The following are the Server variables:

Special (Apache specific)  variables

These are various Special (Apache specific)  variables:


The version of the Apache module API (not the same as the Apache version number, but closely related); used mainly for module development (internally)


Complete HTTP file request string, including method, file requested, and HTTP version used


The resource requested in the HTTP request including string after ? if such present. %{REQUEST_URI} is that part of the URI which follows the domain up to but not including the ?  character of a query string.

And is the only Apache variable that a rewrite rule attempts to match. Apache changed regex engines when it changed versions, so Apache version 1 includes the leading slash in  %{REQUEST_URI} while Apache 2 does not! 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). So now we have:


Full local file system path for the item matching the HTTP request  See Use of REQUEST_FILENAME in Apache mod rewrite

IS_SUBREQ Whether or not the request being processed is an internal subrequest; the value will be “true” if the request is a subrequest, “false” if not

HTTPS A value of “on” indicates SSL/TLS is being used, “off” if not

To use any of the variables from that long list, you wrap the variable name in curly braces, and prefix with a percent sign, like so:


To see RewriteCond in action, first rewrite a RewriteRule to make use of RewriteCond. The old rule looked like this: # Rewrite /category/ to catalog.php RewriteRule ^(\w+)/?$ catalog.php?cat=$1&item=$2 To accomplish the same goal using RewriteCond in conjunction with RewriteRule, use the following:

# Rewrite /category/item/ to catalog.php
RewriteCond %{SCRIPT_FILENAME} ^(\w+)/(\w+)/?$
RewriteRule .* catalog.php?cat=$1&item=$2
Notice how the server variable SCRIPT_FILENAME was used as the test input string. Combining RewriteCond with RewriteRule using these server variables, you can come up with some interesting combinations. The following checks to see if the user’s browser can accept XHTML MIME types, and if so, changes the MIME type header sent for .html files:
RewriteCond %{HTTP_ACCEPT} application/xhtml\+xml
RewriteRule .*\.html$ - [T=application/xhtml+xml]

RewriteCond Flags

To help control RewriteCond further, a couple of flags are provided, similar to the RewriteRule flags.

nocase|NC Like the same-named flag used with RewriteRule, nocase specifies that the regular expression to be evaluated is case-insensitive.

|OR ornext The default chaining method for multiple RewriteCond directives is to use a logical AND. If the ornext flag is used, the two connected RewriteConds are compared with a logical OR. While the RewriteRule and RewriteCond directives deliver a majority of the power in mod_rewrite, there are a handful of other key directives that can help you control your rewriting and solve problems.

Chaining multiple lines together

Important feature of RewriteCond is the ability to chain multiple lines together. When listing multiple RewriteCond statements in a row, they are each treated like a programmatic AND—the RewriteRule at the end will only process if all the RewriteCond matches return true. The previous set of rules could be rewritten using multiple RewriteCond statements, like this:

RewriteCond %{HTTP_ACCEPT} application/xhtml\+xml
RewriteCond %{SCRIPT_FILENAME} \.html$
RewriteRule .* - [T=application/xhtml+xml]
In addition to the standard string-versus-regex comparisons, you can actually make simple comparison and system-check conditionals with RewriteCond. To compare your input string against another simple string, you can use the following as your conditional pattern: <CondPattern >CondPattern =CondPattern

Each of these checks is true if the input string is less than, greater than, or equal to, the CondPattern, respectively. For example, if you wanted to make a certain area of your website forbidden after a given year, you could use the following:

RewriteCond %{TIME_YEAR} >2005
RewriteRule .* - [F]
Along with these simple comparison operators, you have access to six more conditional checks that evaluate the statuses of files and directories: Comparison Operator Meaning

For example, to check to see if an image exists and actually contains some data, you could use the following:

RewriteCond %{REQUEST_FILENAME} \.jpg$
RewriteCond %{REQUEST_FILENAME} !-s
RewriteRule .* - [G]
The first condition checks to see if a .jpeg file is called, and the second condition actually checks to see if the file either doesn’t exist, or is 0 bytes. Notice the use of the exclamation point before the -s conditional pattern. Any conditional pattern used in RewriteCond can be prefixed with an exclamation point, thus negating it—identical to the use of the exclamation point in PHP conditionals.


In most situations, your website URLs will not match your physical file system layout. The root of your website is almost never located at the root (/) of the local file system. In normal operation of Apache server, this is not usually a problem; when using RewriteRule, it can be very problematic. RewriteBase allows you to specify the base or prefix path for a set of URL rewrites. To fully understand the reasoning for RewriteBase, take a look at the following example ruleset used to rewrite a simple set of files:
RewriteEngine On
RewriteRule ^foo\.html$ bar.html [R]
Suppose your web root is being served out of the /www folder of the local file system (that is, your DocumentRoot is set to /www). If you tried to use the preceding rule in a per-directory access file (.htaccess), it would actually result in the request being rewritten incorrectly—instead of your expected file being returned, you get
Why is this? Here is a simplified version of what is happening internally to Apache:
Request: /www/foo.html (local physical path)
/www/foo.html -> foo.html (directory prefix stripped)
foo.html -> bar.html (RewriteRule applied)
bar.html -> /www/bar.html (directory prefix re-applied)
/www/bar.html ->
(domain prefix applied to URL, sent to browser)
To solve this, you simply add a RewriteBase statement to your ruleset:
RewriteEngine On
RewriteBase /
RewriteRule ^foo\.html$ bar.html [R]
In order to get a first-hand glimpse of what is actually going on with mod_rewrite, try out the RewriteLog directive. You can use RewriteLog to specify a log file where a running record of the internal rewrite processing will be sent.

To enable a log of the rewrites alongside the other default Apache log files, use the following: RewriteLog “logs/rewrite_log” When specifying the path for the rewrite log, you can use both absolute and relative paths. If a relative path is used, it will be taken relative to the ServerRoot setting in httpd.conf. Note that the RewriteLog directive is applied on a per-server basis, so it must be placed in either the server config or a virtual host container inside httpd.conf—it is not allowed inside a <Directory> section or .htaccess file.

RewriteLogLevel -- Important for Debugging

To control how verbose the rewrite log records are, you can use the RewriteLogLevel directive. Given a number 0 through 9, with 9 being the most verbose, you can control how much internal processing is recorded. A setting of 0 disables logging altogether, and anything greater than 2 should be used only for debugging—it can slow down Apache on the higher settings.

 If you’d like to delve deeper into the workings of mod_rewrite, check out the mod_rewrite section of the Apache online manual:

Top Visited
Past week
Past month


Old News ;-)

[Jun 12, 2021] A beginner s guide to creating redirects in an .htaccess file - Enable Sysadmin

Jun 10, 2021 |

A beginner's guide to creating redirects in an .htaccess file Use the .htaccess file to manage web sites on shared web hosting platforms.

Posted: June 9, 2021 | by Abdul Rehman

Image by Reginal from Pixabay

Have you ever felt a need to change the configuration of your website running on an Apache webserver without having root access to server configuration files ( httpd.conf )? This is what the .htaccess file is for.

The .htaccess file provides a way to make configuration changes to your website on a per-directory basis. The file is created in a specific directory that contains one or more configuration directives that are applied to that directory and its subdirectories. In shared hosting, you will need to use a .htaccess file to make configuration changes to your server.

[ You might also enjoy: 6 sysadmin skills web developers need ]

Common uses of .htaccess file

The .htaccess file has several use cases. The most common examples include:

In the cloud When not to use .htaccess?

The .htaccess file is commonly used when you don't have access to the main server configuration file httpd.conf or virtual host configuration, which only happens if you have purchased shared hosting. You can achieve all of the above-mentioned use cases by editing the main server configuration file(s) (e.g., httpd.conf ) or virtual host configuration files, so you should not use .htaccess when you have access to those files. Any configuration that you need to put in a .htaccess file can just as effectively be added in a <Directory> section in your main server or virtual host configuration files.

Reasons to avoid using .htaccess

There are two reasons to avoid the use of .htaccess files. Let's take a closer look at them.

First : Performance - When AllowOverride is set to allow the use of .htaccess files, httpd will look for .htaccess files in every directory starting from the parent directory. This will cause a performance impact, whether you're using it or not. The .htaccess file is loaded every time a document is requested from a directory.

To have a full view of the directives that it must apply, httpd will always look for .htaccess files starting with the parent directory until it reaches the target sub-directory. If a file is requested from directory /public_html/test_web/content , httpd must look for the following files:

So, four file-system accesses were performed for each file access from a sub-directory content even if the file is not present.

Second : Security - granting users permission to make changes in .htaccess files gives them full control over the server configuration of that particular website or virtual host. Any directive in the .htaccess file has the same effect as any placed in the httpd configuration file itself, and changes made to this file are live instantly without a need to restart the server. This can become risky in terms of the security of a webserver and a website.

Enable the .htaccess file

To enable the .htaccess file, you need to have sudo/root privileges on the server.

Open the httpd configuration file of your website:


You should add the following configuration directive in the server's virtual host file to allow the .htaccess file in the DocumentRoot directory. If the following lines are not added, the .htaccess file will not work:

<Directory /var/www/>
    Options Indexes FollowSymLinks
    AllowOverride All
    Require all granted

In the case of shared hosting, this is already allowed by the hosting service providers. All you need to do is to create a .htaccess file in the public_html directory to which the service provider has given you access and to which you will upload your website files.

Redirect URLs

If your goal is to simply redirect one URL to another, the Redirect directive is the best option you can use. Whenever a request comes from a client on an old URL, it forwards it to a new URL at a new location.

If you want to do a complete redirect to a different domain, you can set the following:

# Redirect to a different domain
Redirect 301 "/service" ""

If you just want to redirect an old URL to a new URL on the same host:

# Redirect to a URL on the same domain or host
Redirect 301 "/old_url.html" "/new_url.html"
Load a custom 404 Error page
Kubernetes and OpenShift

For a better user experience, load a custom error page when any of the links on your website point to the wrong location or the document has been deleted.

To create a custom 404 page, simply create a web page that will work as a 404 page and then add the following code to your .htaccess file:

ErrorDocument 404 /error/pagenotfound.html

You should change /error/pagenotfound.html to the location of your 404 page.

Force the use of HTTPS instead of HTTP for your website

If you want to force your website to use HTTPS, you need to use the RewriteEngine module in the .htaccess file. First of all, you need to turn on the RewriteEngine module in the .htaccess file and then specify the conditions you want to check. If those conditions are satisfied, then you apply rules to those conditions.

The following code snippet rewrites all the requests to HTTPS:

# Turn on the rewrite engine
RewriteEngine On

# Force HTTPS and WWW
RewriteCond %{HTTP_HOST} !^www\.(.*)$ [OR,NC]
RewriteCond %{https} off  
RewriteRule ^(.*)$$1 [R=301,L]

Let's go through each line.

RewriteEngine on turns on the RewriteEngine module. This is required; otherwise, conditions and rules won't work.

The first condition checks if www is entered. [OR, NC] stands for no case , which means even if the entered URL has a mix of upper or lowercase case letters.

Next, it checks if the HTTPS protocol was already entered by the user. %{https} off means that HTTPS protocol was not used.

When the RewriteCond is satisfied, we use RewriteRule to redirect the URL to HTTPS. Note that in this case, all URLs will be redirected to HTTPS whenever any request is made.

[Oct 21, 2017] Apache2 mod_rewrite and %{REQUEST_FILENAME} - Sysadmandine

February 23, 2010 admin
Notable quotes:
"... I must admit I read the description for REQUEST_FILENAME in apache2.2 several times before noticing that it was just the answer too used to read too fast! Thanks to this old post that made me re-read slower ! ..."
Oct 21, 2017 |

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule ^/(.*)$ /index.php?rt=$1 [L,QSA]

This means : if the requested file is not a real file, and isn't a directory, and isn't a symlink, then redirect to index.php.

I was really surprised to discover that it doesn't work. Though, everybody seems to use this syntax ! I checked my apache version : Apache/2.2.9 (Debian), nothing special with this one I guess.
To understand what Apache was doing with my rewrites, I activated the rewrite log :

RewriteLog /var/log/apache2/rewrite.log

Here's what I got (the interesting part, cause I got a looot more !) :

[blah blah blah] (2) init rewrite engine with requested uri /toto.htm
[blah blah blah] (3) applying pattern '^/(.*)$' to uri '/toto.htm'
[blah blah blah] (4) RewriteCond: input='/toto.htm' pattern='!-f' =&gt; matched
[blah blah blah] (4) RewriteCond: input='/toto.htm' pattern='!-d' =&gt; matched
[blah blah blah] (4) RewriteCond: input='/toto.htm' pattern='!-l' =&gt; matched
[blah blah blah] (2) rewrite '/toto.htm' -&gt; '/index.php?rt=toto.htm'

So apaches verifies only '/toto.htm' and not the whole path for "%{REQUEST_FILENAME}"? I thought though it was the whole path let's verify in the doc.
From , by habit (cause I used apache 2.0 a lot more than apache 2.2 from now on) :

REQUEST_FILENAME : The full local filesystem path to the file or script matching the request.

Hmm. But I use apache version 2.2, so what do they say here :

REQUEST_FILENAME : The full local filesystem path to the file or script matching the request, if this has already been determined by the server at the time REQUEST_FILENAME is referenced. Otherwise, such as when used in virtual host context, the same value as REQUEST_URI.


REQUEST_URI : The resource requested in the HTTP request line. (In the example above, this would be "/index.html".)

Ok, I understand, I use virtual hosts (like everybody, uh?), so the real syntax for my needs is :

RewriteRule ^/(.*)$ /index.php?rt=$1 [L,QSA]

This works even if it doubles the "/" between each variable (one / at the end of DOCUMENT_ROOT, and another at the beginning of REQUEST_FILENAME).

Here's the rewrite log showing that it works :

[blah blah blah] (2) init rewrite engine with requested uri /toto.htm
[blah blah blah] (3) applying pattern '^/(.*)$' to uri '/toto.htm'
[blah blah blah] (4) RewriteCond: input='/path/to/documentroot//toto.htm' pattern='!-f' =&gt; not-matched
[blah blah blah] (1) pass through /toto.htm

Now I can disable this log if I want to keep space on my disk.

I must admit I read the description for REQUEST_FILENAME in apache2.2 several times before noticing that it was just the answer too used to read too fast! Thanks to this old post that made me re-read slower ! 😉

Blocking unwanted visitors

 18 #order allow,deny
 19 #allow from all
 20 #
 22 deny from
 23 deny from
 24 deny from
 25 deny from
 26 deny from
 27 deny from
 29 RewriteCond %{HTTP_USER_AGENT} libwww.* [OR]
 30 RewriteCond %{HTTP_USER_AGENT} MaMa.* [OR]
 31 RewriteCond %{HTTP_USER_AGENT} MLBot.*
 32 RewriteRule ^.+ - [F]
 34 RewriteCond %{QUERY_STRING} !^$
 35 RewriteRule .+ - [F]
 37 RewriteCond %{REQUEST_URI} \.shtml/. [OR]
 38 RewriteCond %{REQUEST_URI} \.(php|asp|dll)[/?%]$)
 39 RewriteRule ^.+ - [F]
 41 RewriteCond %{HTTP_REFERER} !^*$      [NC]
 42 RewriteCond %{HTTP_REFERER} !^*$      [NC]
 43 RewriteCond %{HTTP_REFERER} !^*$      [NC]
 44 RewriteCond %{HTTP_REFERER} !^*$      [NC]
 45 RewriteRule .+\.(jpg|jpeg|gif|png|bmp)$
    nternet.gif [R,NC]

Recommended Links

Google matched content

Softpanorama Recommended

Top articles


Top articles




Groupthink : Two Party System as Polyarchy : Corruption of Regulators : Bureaucracies : Understanding Micromanagers and Control Freaks : Toxic Managers :   Harvard Mafia : Diplomatic Communication : Surviving a Bad Performance Review : Insufficient Retirement Funds as Immanent Problem of Neoliberal Regime : PseudoScience : Who Rules America : Neoliberalism  : The Iron Law of Oligarchy : Libertarian Philosophy


War and Peace : Skeptical Finance : John Kenneth Galbraith :Talleyrand : Oscar Wilde : Otto Von Bismarck : Keynes : George Carlin : Skeptics : Propaganda  : SE quotes : Language Design and Programming Quotes : Random IT-related quotesSomerset Maugham : Marcus Aurelius : Kurt Vonnegut : Eric Hoffer : Winston Churchill : Napoleon Bonaparte : Ambrose BierceBernard Shaw : Mark Twain Quotes


Vol 25, No.12 (December, 2013) Rational Fools vs. Efficient Crooks The efficient markets hypothesis : Political Skeptic Bulletin, 2013 : Unemployment Bulletin, 2010 :  Vol 23, No.10 (October, 2011) An observation about corporate security departments : Slightly Skeptical Euromaydan Chronicles, June 2014 : Greenspan legacy bulletin, 2008 : Vol 25, No.10 (October, 2013) Cryptolocker Trojan (Win32/Crilock.A) : Vol 25, No.08 (August, 2013) Cloud providers as intelligence collection hubs : Financial Humor Bulletin, 2010 : Inequality Bulletin, 2009 : Financial Humor Bulletin, 2008 : Copyleft Problems Bulletin, 2004 : Financial Humor Bulletin, 2011 : Energy Bulletin, 2010 : Malware Protection Bulletin, 2010 : Vol 26, No.1 (January, 2013) Object-Oriented Cult : Political Skeptic Bulletin, 2011 : Vol 23, No.11 (November, 2011) Softpanorama classification of sysadmin horror stories : Vol 25, No.05 (May, 2013) Corporate bullshit as a communication method  : Vol 25, No.06 (June, 2013) A Note on the Relationship of Brooks Law and Conway Law


Fifty glorious years (1950-2000): the triumph of the US computer engineering : Donald Knuth : TAoCP and its Influence of Computer Science : Richard Stallman : Linus Torvalds  : Larry Wall  : John K. Ousterhout : CTSS : Multix OS Unix History : Unix shell history : VI editor : History of pipes concept : Solaris : MS DOSProgramming Languages History : PL/1 : Simula 67 : C : History of GCC developmentScripting Languages : Perl history   : OS History : Mail : DNS : SSH : CPU Instruction Sets : SPARC systems 1987-2006 : Norton Commander : Norton Utilities : Norton Ghost : Frontpage history : Malware Defense History : GNU Screen : OSS early history

Classic books:

The Peter Principle : Parkinson Law : 1984 : The Mythical Man-MonthHow to Solve It by George Polya : The Art of Computer Programming : The Elements of Programming Style : The Unix Hater’s Handbook : The Jargon file : The True Believer : Programming Pearls : The Good Soldier Svejk : The Power Elite

Most popular humor pages:

Manifest of the Softpanorama IT Slacker Society : Ten Commandments of the IT Slackers Society : Computer Humor Collection : BSD Logo Story : The Cuckoo's Egg : IT Slang : C++ Humor : ARE YOU A BBS ADDICT? : The Perl Purity Test : Object oriented programmers of all nations : Financial Humor : Financial Humor Bulletin, 2008 : Financial Humor Bulletin, 2010 : The Most Comprehensive Collection of Editor-related Humor : Programming Language Humor : Goldman Sachs related humor : Greenspan humor : C Humor : Scripting Humor : Real Programmers Humor : Web Humor : GPL-related Humor : OFM Humor : Politically Incorrect Humor : IDS Humor : "Linux Sucks" Humor : Russian Musical Humor : Best Russian Programmer Humor : Microsoft plans to buy Catholic Church : Richard Stallman Related Humor : Admin Humor : Perl-related Humor : Linus Torvalds Related humor : PseudoScience Related Humor : Networking Humor : Shell Humor : Financial Humor Bulletin, 2011 : Financial Humor Bulletin, 2012 : Financial Humor Bulletin, 2013 : Java Humor : Software Engineering Humor : Sun Solaris Related Humor : Education Humor : IBM Humor : Assembler-related Humor : VIM Humor : Computer Viruses Humor : Bright tomorrow is rescheduled to a day after tomorrow : Classic Computer Humor

The Last but not Least Technology is dominated by two types of people: those who understand what they do not manage and those who manage what they do not understand ~Archibald Putt. Ph.D

Copyright © 1996-2021 by Softpanorama Society. was initially created as a service to the (now defunct) UN Sustainable Development Networking Programme (SDNP) without any remuneration. This document is an industrial compilation designed and created exclusively for educational use and is distributed under the Softpanorama Content License. Original materials copyright belong to respective owners. Quotes are made for educational purposes only in compliance with the fair use doctrine.

FAIR USE NOTICE This site contains copyrighted material the use of which has not always been specifically authorized by the copyright owner. We are making such material available to advance understanding of computer science, IT technology, economic, scientific, and social issues. We believe this constitutes a 'fair use' of any such copyrighted material as provided by section 107 of the US Copyright Law according to which such material can be distributed without profit exclusively for research and educational purposes.

This is a Spartan WHYFF (We Help You For Free) site written by people for whom English is not a native language. Grammar and spelling errors should be expected. The site contain some broken links as it develops like a living tree...

You can use PayPal to to buy a cup of coffee for authors of this site


The statements, views and opinions presented on this web page are those of the author (or referenced source) and are not endorsed by, nor do they necessarily reflect, the opinions of the Softpanorama society. We do not warrant the correctness of the information provided or its fitness for any purpose. The site uses AdSense so you need to be aware of Google privacy policy. You you do not want to be tracked by Google please disable Javascript for this site. This site is perfectly usable without Javascript.

Last modified: December 26, 2017