<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>AskApache &#187; Search Results  &#187;  htaccess+rewrites</title>
	<atom:link href="http://www.askapache.com/search/htaccess+rewrites/feed/rss2/" rel="self" type="application/rss+xml" />
	<link>http://www.askapache.com</link>
	<description>Advanced Web Development</description>
	<lastBuildDate>Sun, 29 Jan 2012 12:04:08 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Htaccess Rewrites for Moving Urls</title>
		<link>http://www.askapache.com/htaccess/htaccess-rewrites.html</link>
		<comments>http://www.askapache.com/htaccess/htaccess-rewrites.html#comments</comments>
		<pubDate>Sat, 29 Oct 2011 14:41:55 +0000</pubDate>
		<dc:creator>AskApache</dc:creator>
				<category><![CDATA[Htaccess]]></category>
		<category><![CDATA[301 Redirects]]></category>

		<guid isPermaLink="false">http://www.askapache.com/?p=5231</guid>
		<description><![CDATA[<p><a href="http://www.askapache.com/htaccess/htaccess-rewrites.html"></a><a href="http://www.askapache.com/htaccess/htaccess-rewrites.html"><cite>AskApache.com</cite></a></p><p>This is part 2 of the <a href="http://www.askapache.com/htaccess/htaccess.html" title="Htaccess Tutorial like no other">exhaustive Htaccess Tutorial</a>.  I realized it was so lengthy that search engines and visitors were having real problems with it, so I moved half of it here.  But this gave me the opportunity to add a ton of new stuff that I hadn't been able to add to the main htaccess tutorial.  &#8230; <a href="http://www.askapache.com/htaccess/htaccess-rewrites.html" class="read_more">Read the rest</a></p>]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.askapache.com/htaccess/htaccess-rewrites.html"></a><a href="http://www.askapache.com/htaccess/htaccess-rewrites.html"><cite>AskApache.com</cite></a></p><p>This is part 2 of the <a href="http://www.askapache.com/htaccess/htaccess.html" title="Htaccess Tutorial like no other">exhaustive Htaccess Tutorial</a>.  I realized it was so lengthy that search engines and visitors were having real problems with it, so I moved half of it here.  But this gave me the opportunity to add a ton of new stuff that I hadn't been able to add to the main htaccess tutorial.  And now this new part 2 is already twice as big as the original!  To sum up, this is a work in progress.</p>


<h2>Moving Half of Original Tutorial to a new URL - SEO Rewriting</h2>
<p>Well, the original tutorial was at /htaccess/apache-htaccess.html, but it was such a huge article that search engines were dropping it!  So I split it into 3 new urls.</p>
<ol>
<li>/htaccess/htaccess.html - 1</li>
<li>/htaccess/htaccess-rewrites.html - Rewrites</li>
<li>/htaccess/apache-htaccess-2.html - Part 2</li>
</ol>

<p>The /htaccess/apache-htaccess-2.html is a lot of unfinished new stuff, and the /htaccess/htaccess-rewrites.html (this very page) still needs to be split several times to get the filesize down.</p>

<h3>301 Link Juice</h3>
<p>The /apache-htaccess.html url has been around since 2006, and it was full of original ideas and examples for using htaccess.  Almost every htaccess guide or tutorial published since then has many of the examples and ideas from that tutorial, (I encourage people to modify and republish everything on this site according to copyright).  I know it, the authors sometimes know it, but the main point is Google for sure knows it.  That's the beauty of creating unique content, Google sees that.  So that /apache-htaccess.html link has extreme link juice, from all the sites, books, papers, and presentations that have linked to it since 2006.</p>

<h4>Filesize Is important</h4>
<p>I like to use my blog as a way to keep notes about my research organized, and I am extremely good at doing research, unfortunately, that means I have a huge article.  The filesize for the html alone is larger than all the other resources like javascript and images, combined.</p>
<ul>
<li>So that means it is very difficult to view on a mobile device, or a slow connection.</li>
<li>For google-bot and other search engine crawlers and robots, this is a huge problem (I made a big mistake letting it get that size).</li>
<li>The robot has to parse an enormous single html file, containing hundreds/thousands of external and internal links, and its such an issue they can decide to just skip indexing that url until the filesize is manageable.</li>
<li>Once again, it's all about the human experience, a huge single file is not good for anyone who isn't printing it out to read offline.</li>
</ul>

<h4>Starting Fresh without losing juice</h4>
<p>So since the page wasn't being indexed much since it was so huge, I decided to split up the content into new separate urls and utilize a 301 Redirect to transfer all the link juice from /apache-htaccess.html to /htaccess.html.</p>


<h2>301 Redirect Timeline</h2>
<ol>
<li>Now, the idea is to take the first pages from the original multi-page guide, do a little improvement on that content, and save it to the new url /htaccess.html.</li>
<li>Then just continue taking the next page from the remaining original guide and creating new pages using the original links structure.  /apache-htaccess-2.html, /apache-htaccess-3.html, etc.. This is a secondary backup to the new /htaccess.html url, which will receive the 301 link juice from the old url, but these secondary pages will help keep the links on external sites good.</li>
<li>Then, I setup a 301 Redirect in my .htaccess file to redirect the old url to the new /htaccess.html url.</li>
<li>Finally, I delete the old url and it is replaced forever by a 301 Redirect pointing to my new location, filesize problems eliminated.</li>
</ol>

<h3>301 Redirect Code Used</h3>
<p>This is so easy to do with RedirectMatch, way faster and easier than using mod_rewrite to handle this, and much less overhead.  Note that this is a general command that I will leave up for a few weeks and slowly tighten it up by looking at my Google Analytics and Apache Logs.  For instance, this first redirectmatch rule is an older RedirectMatch I still have active to redirect all the old links pointing at /2006/htaccess/apache-htaccess.html to /htaccess/apache-htaccess.html from when I ditched the date-based permalinks back in 2007, and you can see it is a little tighter than the 2nd one which also redirects requests for apache-htaccess.html/feed/ or trackback or whatever.</p>
<pre>RedirectMatch 301 ^/2006/.*apache-htaccess.html$ http://www.askapache.com/htaccess/apache-htaccess.html
RedirectMatch 301 ^/.*apache-htaccess.html(.*)$ http://www.askapache.com/htaccess/htaccess.html$1</pre>



<h2>Advanced 301 Redirects for SEO</h2>
<p>I wrote a couple of articles that go into detail about maximizing the SEO with linking and redirects, it remains one of my most helpful articles to anyone trying to rank higher the right way, the Google way.. <a href="http://www.askapache.com/seo/seo-advanced-pagerank-indexing.html">SEO Secrets of AskApache Part 2</a></p><p><a href="http://www.askapache.com/htaccess/htaccess-rewrites.html"></a><a href="http://www.askapache.com/htaccess/htaccess-rewrites.html">Htaccess Rewrites for Moving Urls</a> originally appeared on <cite>AskApache.com</cite> </p>]]></content:encoded>
			<wfw:commentRss>http://www.askapache.com/htaccess/htaccess-rewrites.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>3 Ways to Serve PDF Files using Htaccess Cookies, Headers, Rewrites</title>
		<link>http://www.askapache.com/htaccess/pdf-cookies-headers-rewrites.html</link>
		<comments>http://www.askapache.com/htaccess/pdf-cookies-headers-rewrites.html#comments</comments>
		<pubDate>Sun, 21 Aug 2011 03:07:53 +0000</pubDate>
		<dc:creator>AskApache</dc:creator>
				<category><![CDATA[Htaccess]]></category>

		<guid isPermaLink="false">http://www.askapache.com/?p=2328</guid>
		<description><![CDATA[<p><a class="IFL" href="http://www.askapache.com/htaccess/pdf-cookies-headers-rewrites.html"><img height="60" width="45" src='http://uploads.askapache.com/2007/11/60x45_acrobat_trefoil.gif' alt='Adobe PDF' /></a>FYI, using the <a href="http://www.askapache.com/htaccess/mod_rewrite-variables-cheatsheet.html">Mod_Rewrite Variables Cheatsheet</a> makes this example, and all advanced .htaccess code easier to understand.  This demo lets you set a cookie with 1 of 3 values, then you just request the pdf file with a normal link click and get 1 of 3 different responses. This is accomplished with a nice bit of <a href="http://www.askapache.com/htaccess/htaccess.html">.htaccess</a> code.<br class="C" /></p>
<div class="cnote">
<p><strong>Set PDF Viewing Mode</strong> - <kbd id="pdfr">Make a selection, then click the view pdf button.</kbd></p>
<p><span id="pdfi" class="FL btnn">Inline</span> <span id="pdfa" class="FL btnn">Download</span> <span id="pdfs" class="FL btnn">Save As</span> <a class="FL btnn" style="margin-left:10px; border-top:1px solid #96F8AF; background:-moz-linear-gradient(center top , #3E9D43, #6ED766) repeat scroll 0 0 transparent;margin-left:20px;" rel="nofollow" href="http://www.askapache.com/storage/pdf/AskApache-Test.pdf">View PDF using selected mode &#187;</a><br class="C" /></p>
</div>]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.askapache.com/htaccess/pdf-cookies-headers-rewrites.html"></a><a href="http://www.askapache.com/htaccess/pdf-cookies-headers-rewrites.html"><cite>AskApache.com</cite></a></p><p><a class="IFL" id="id10" href="http://www.askapache.com/htaccess/pdf-cookies-headers-rewrites.html"></a>FYI, using the <a href="http://www.askapache.com/htaccess/mod_rewrite-variables-cheatsheet.html">Mod_Rewrite Variables Cheatsheet</a> makes this example, and all advanced .htaccess code easier to understand.  This demo lets you set a cookie with 1 of 3 values, then you just request the pdf file with a normal link click and get 1 of 3 different responses. This is accomplished with a nice bit of <a href="http://www.askapache.com/htaccess/htaccess.html">.htaccess</a> code.<br /><br />As I explain the htaccess code that achieves this, keep in mind this is merely one simple application for this code.  It's much more advanced than your basic htaccess trick, notice how this htaccess acts like a php script, very unusual..  I really wanted to share this trick after I created it for one of my clients because this is the tip of the iceberg.  Another use would be to display an alternate style sheet depending on a users theme preference.  The coolest thing is that it uses multiple advanced .htaccess ideas.  This code uses mod_headers to set the Content-Disposition header for forcing a download and uses mod_rewrite to: Send different Content-Type headers, Check the value of a cookie, Set environment variables for use later by mod_headers header directive<br class="C" /></p>

<div class="cnote">
<p><strong>Set PDF Viewing Mode</strong> - <kbd id="pdfr">Make a selection, then click the view pdf button.</kbd></p>
<p><span id="pdfi" class="FL btnn">Inline</span> <span id="pdfa" class="FL btnn">Download</span> <span id="pdfs" class="FL btnn">Save As</span> <a class="FL btnn" style="margin-left:10px; border-top:1px solid #96F8AF; background:-moz-linear-gradient(center top , #3E9D43, #6ED766) repeat scroll 0 0 transparent;margin-left:20px;" rel="nofollow" href="http://www.askapache.com/storage/pdf/AskApache-Test.pdf">View PDF using selected mode &raquo;</a><br class="C" /></p>
</div>


<h2>What's Going On</h2>
<p>There are 3 different ways for a server to send a pdf file in response to a request for one.  This causes 3 different ways to open/view the pdf file in the clients browser.</p>
<ol>
<li>The browser display's a <strong>"Save File As"</strong> dialog, allowing you to save the file or open.</li>
<li>The browser opens the pdf file <strong>"Inline"</strong>, opening the pdf file in the browser like a web page.</li>
<li>The browser "<strong>Downloads</strong>" the pdf file automatically as an "<strong>Attachment</strong>" and then causes an external pdf reader program like adobe reader to open the file.</li>
</ol>
<p>Some people prefer to have the option of saving the file to view later, some prefer opening it with an external program, and some just like the pdf file to load right in the browser...  The point is that by using .htaccess, we can let them choose any of the 3 methods and save their preference for all further pdf files requested from our site by that user.</p>





<h2>How It Works</h2>
<p>When you click on one of the 3 demo buttons above, "Inline", "Save As", or "Download", a cookie named <code>askapache_pdf</code> is saved in your browser using the javascript below, with the value being set to which button you clicked.  Then when you request the pdf file the .htaccess code below uses mod_rewrite to read the value of the askapache_pdf cookie, and depending on which was your preference it will send alternate HTTP Headers that control how your browser handles the file.</p>


<h3>Unique HTTP Headers Returned</h3>
<p>When it comes down to it, the following information is the 3 modes.  Notice each one is different, because these headers are the only thing controlling how your browser handles the file.</p>
<h4>Save As Mode (askapache_pdf=s)</h4>
<pre>Content-Disposition: attachment
Content-Type: application/pdf</pre>
<h4>Inline Mode (askapache_pdf=i)</h4>
<pre>Content-Type: application/pdf</pre>
<h4>Download Mode (askapache_pdf=a)</h4>
<pre>Content-Type: application/octet-stream</pre>


<h3>Htaccess Demo File</h3>
<p>For the demo I created the folder /storage/pdf/ and this is the .htaccess file at /storage/pdf/.htaccess</p>
<p>The default Content-Type for .pdf files.  This will make .pdf files default Content-Type header have  the value 'application/pdf' - but the default can be overridden by using RewriteRule with the <code>[T=&#039;different/type&#039;]</code></p>
<pre>AddType application/pdf .pdf</pre>

<p>Turn on the rewrite engine if its already on you dont need this </p>
<pre>RewriteEngine On</pre>

<p>Skip RewriteRules if not .pdf request, like autoindexing. The next [2] RewriteRule directives are specific for .pdf files so if the filename requested does not end in .pdf then the <code>[S=2]</code> instructs the next 2 RewriteRule  directives to be completely skipped.</p>
<pre>RewriteRule !.*\.pdf$ - [S=2]</pre>


<p>The first RewriteCond checks to see if the askapache_pdf cookie is NOT set.  The second RewriteCond checks to see if the askapche_pdf cookie has the value of s, which is the value corresponding to someone clicking the "Save As" button.</p>
<p>The <code>[NC,OR]</code> flag means that if the cookie askapache_pdf does not exist, OR (next cond) if the askapache_pdf cookie does exist and is set to 's' then process the RewriteRule.  If neither cond is true the rewriterule is skipped.</p>
<p>If one of the RewriteCond is true, then the RewriteRule is processed.   The RewriteRule applies to any/all requests (.*) but doesn't rewrite anything (-) This RewriteRule sets an Apache environment variable ASKAPACHE_PDFS to have the value of 1 if either rewritecond is true.  The variable can be checked by any directives following the rewriterule in the whole htaccess file.  The ASKAPACHE_PDFS ends in S because if this variable exists then it means the users preference is 'Save As'</p>
<p>Notice that if the user requested the pdf file without selecting a preference i.e. no cookie exists, then the ASKAPACHE_PDFS variable is still set. This just lets us pick the default preference for them, in this example the default is 'Save As'</p>
<pre>RewriteCond %{HTTP_COOKIE} !^.*askapache_pdf.*$ [NC,OR]
RewriteCond %{HTTP_COOKIE} ^.*askapache_pdf=s.*$ [NC]
RewriteRule .* - [E=ASKAPACHE_PDFS:1]</pre>

<p>The RewriteCond checks the askapache_pdf cookie for the value 'a' which 'a' represents 'Download'</p>
<p>If the cookies value is 'a' then the RewriteRule overrides the default Content-Type from 'application/pdf' set with AddType earlier, to 'application/octet-stream', which is a special content-type that tells the browser that the file cannot be loaded by the browser 'Inline', but must be saved which will be opened by an external viewer depending on browser configuration and plugins.</p>
<pre>RewriteCond %{HTTP_COOKIE} ^.*askapache_pdf=a.*$
RewriteRule .* - [T=application/octet-stream]</pre>

<p>This is superfly.  If the cookie/users-preference was 'Save As' (s) then the RewriteRule above the last one set the environment variable ASKAPACHE_PDFS to have the value 1.  The Header directive here is ONLY processed in that variable ASKAPACHE_PDFS exists.  That is what the end 'env=ASKAPACHE_PDFS' does, it is the condition that must be met or the Header directive is skipped.  If the ASKAPACHE_PDFS environment variable set by RewriteRule does exist then the header directive adds the header '<code>Content-Disposition: attachment</code>' to  the normal Response Headers.  The 'Content-Disposition: attachment' header instructs your browser to present you with the 'Save As' dialog box allowing you to choose whether you want to save or open.</p>
<pre>Header set Content-Disposition "attachment" env=ASKAPACHE_PDFS</pre>






<h2>Javascript used by Demo</h2>
<p>The best place for javascript is quirksmode, here is a definitive article on setting, reading, parsing, etc.. <a title="I am a javascript cookie monster" href="http://www.quirksmode.org/js/cookies.html">COOKIES</a>.</p>
<p>Note, I now prefer using jQuery over my AAJS javascript library.  Also, the whole using cookies aspect is just to highlight some advanced htaccess, you can accomplish this much easier without javascript or cookies.</p>
<pre>if(!gi(&#039;pdfr&#039;))return;
var pdfr=gi(&#039;pdfr&#039;);
var cval=getCookie(&#039;askapache_pdf&#039;);
&nbsp;
if(cval==&#039;i&#039;){pdfr.innerHTML=&#039;Currently set to "Inline".&#039;;}
else if(cval==&#039;a&#039;){pdfr.innerHTML=&#039;Currently set to "Download" mode.&#039;;}
else if(cval==&#039;s&#039;){pdfr.innerHTML=&#039;Currently set to "Save As" mode.&#039;;}
&nbsp;
addMyEvent(gi(&#039;pdfi&#039;),"mousedown",function(){
  setCookie("askapache_pdf", "i", "", "/", "www.askapache.com"); gi(&#039;pdfr&#039;).innerHTML = &#039;Changed mode to "Inline".&#039;; return false; });
addMyEvent(gi(&#039;pdfa&#039;),"mousedown",function(){
  setCookie("askapache_pdf", "a", "", "/", "www.askapache.com"); gi(&#039;pdfr&#039;).innerHTML = &#039;Changed mode to "Download".&#039;; return false; });
addMyEvent(gi(&#039;pdfs&#039;),"mousedown",function(){
  setCookie("askapache_pdf", "s", "", "/", "www.askapache.com"); gi(&#039;pdfr&#039;).innerHTML = &#039;Changed mode to "Save As".&#039;; return false; });</pre>

<h2>Alternative Method - No Cookies + PHP</h2>
<p>This is what I came up with first for my client, and then while programming the php I noticed.. Hey!  I think I can do the same thing using .htaccess, which would save me on cpu/memory/potential security/etc.. but this works great too.  Though you will need to hack the code to get it working probably..</p>
<p>Note that the .htaccess rewrite code I used here used FILENAME-i.pdf or FILENAME-s.pdf to pass the preference to the pdf-dl.php script, it also worked for FILENAME.pdf?i=i</p>

<h3>pdf-dl.php</h3>
<pre>&lt;?php
if (
  !isset($_GET[&#039;file&#039;])
  || ($f=$_GET[&#039;file&#039;])===false
  || ($fp=@fopen($f,"rb"))===false
  || ($fi=pathinfo($f))===false
  || ($fi[&#039;fsize&#039;]=filesize($f))===false
  || strtolower($fi["extension"])!=&#039;pdf&#039;
) die(&#039;Failed&#039;);
&nbsp;
ob_start();
header(&#039;Accept-Ranges: bytes&#039;);
header("Content-Length: {$fi[&#039;fsize&#039;]}");
header(&#039;Content-Type: application/pdf&#039;);
if(!isset($_GET[&#039;i&#039;])) header("Content-Disposition: attachment; filename=\"{$fi[&#039;basename&#039;]}\"");
&nbsp;
$sent = 0;
while ( !feof($fp) &amp;&amp; $sent &lt; $fi[&#039;fsize&#039;] &amp;&amp; ($buf = fread($fp, 8192)) != &#039;&#039; ){
  echo $buf;
  $sent += strlen($buf);
  flush();  ob_flush();
}
fclose($fp);
exit;
?&gt;</pre>


<h3>Alternate Method .htaccess</h3>
<p>Deny direct request to pdf-dl.php file</p>
<pre>RewriteCond %{THE_REQUEST} ^.*pdf-dl\.php.*$ [NC]
RewriteRule .* - [F]</pre>
<p>Handle PDF files named anything-i.pdf as inline</p>
<pre>RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ([^/]*)-i\.pdf$  /cgi-bin/pdf-dl.php?i=i&amp;file=%{DOCUMENT_ROOT}/storage/pdf/$1.pdf [L,NC,QSA,S=1]</pre>
<p>Handle PDF files without -i.pdf as attachments</p>
<pre>RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ([^/]*)\.pdf$  /cgi-bin/pdf-dl.php?file=%{DOCUMENT_ROOT}/storage/pdf/$1.pdf [L,NC,QSA]</pre>




<h2>More Info</h2>
<p>The following is more information about the Content-Dispositon header and related subjects for fast readers.</p>

<h3>Interesting Reading</h3>
<p>Here is the thread of the original draft proposal for the Content-Disposition header.</p>
<ul>
<li><a href="http://www.imc.org/ietf-822/old-archive1/msg03620.html">Content-Disposition Header</a>, <em>Rens Troost - 22 Jun 1993</em>
<ul>
<li><a href="http://www.imc.org/ietf-822/old-archive1/msg03629.html">Re: Content-Disposition Header</a>, <em>Nathaniel Borenstein</em>
<ul>
<li><a href="http://www.imc.org/ietf-822/old-archive1/msg03630.html">Re: Content-Disposition Header</a>, <em>Gabe Beged-Dov</em>
<ul>
<li><a href="http://www.imc.org/ietf-822/old-archive1/msg03631.html">Re: Content-Disposition Header</a>, <em>Rens Troost</em></li>
<li><a href="http://www.imc.org/ietf-822/old-archive1/msg03635.html">Re: Content-Disposition Header</a>, <em>Gabe Beged-Dov</em></li>
<li><a href="http://www.imc.org/ietf-822/old-archive1/msg03641.html">Content-Disposition Header and multipart/alternative</a>, <em>Rens Troost</em></li>
<li><a href="http://www.imc.org/ietf-822/old-archive1/msg03645.html">Re: Content-Disposition Header and multipart/alternative</a>, <em>Nathaniel Borenstein</em></li>
</ul>
</li>
<li><a href="http://www.imc.org/ietf-822/old-archive1/msg03632.html">Re: Content-Disposition Header</a>, <em>Keith Moore</em>
<ul>
<li><a href="http://www.imc.org/ietf-822/old-archive1/msg03633.html">Re: Content-Disposition Header</a>, <em>Nathaniel Borenstein</em></li>
<li><a href="http://www.imc.org/ietf-822/old-archive1/msg03634.html">Re: Content-Disposition Header</a>, <em>Ed Levinson (Contractor)</em></li>
<li><a href="http://www.imc.org/ietf-822/old-archive1/msg03636.html">Re: Content-Disposition Header</a>, <em>Keith Moore</em></li>
<li><a href="http://www.imc.org/ietf-822/old-archive1/msg03640.html">Re: Content-Disposition Header</a>, <em>Rens Troost</em></li>
<li><a href="http://www.imc.org/ietf-822/old-archive1/msg03650.html">Re: Content-Disposition Header</a>, <em>Harald Tveit Alvestrand</em></li>
</ul>
</li>
<li><a href="http://www.imc.org/ietf-822/old-archive1/msg03621.html">Re: Content-Disposition Header</a>, <em>Steve Dorner</em>
<ul>
<li><a href="http://www.imc.org/ietf-822/old-archive1/msg03622.html">Re: Content-Disposition Header</a>, <em>Rens Troost</em>
<ul>
<li><a href="http://www.imc.org/ietf-822/old-archive1/msg03624.html">Re: Content-Disposition Header</a>, <em>Keith Moore</em></li>
</ul>
</li>
</ul>
</li>
<li><a href="http://www.imc.org/ietf-822/old-archive1/msg03652.html">Re: Content-Disposition Header</a>, <em>Carlyn M. Lowery</em></li>
</ul>
</li>
</ul>
</li>
</ul>



<h3>Intense Reading</h3>
<ul>
<li><a href="http://www2.roguewave.com/support/docs/leif/sourcepro/html/protocolsug/10-1.html">Using the MIME Headers Effectively</a></li>
<li><a href="http://www.iana.org/assignments/mail-cont-disp">Mail Content Disposition Values and Parameters</a></li>
<li><cite><a href="http://rfc.askapache.com/rfc1766/rfc1766.txt">Tags for the Identification of Languages</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc1436/rfc1436.txt">The Internet Gopher Protocol (a distributed document search and retrieval protocol)</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc1630/rfc1630.txt">Universal Resource Identifiers in WWW</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc1738/rfc1738.txt">Uniform Resource Locators (URL)</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc1866/rfc1866.txt">Hypertext Markup Language - 2.0</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc1945/rfc1945.txt">Hypertext Transfer Protocol -- HTTP/1.0</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc2045/rfc2045.txt">Multipurpose Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc1123/rfc1123.txt">Requirements for Internet Hosts -- Communication Layers</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc822/rfc822.txt">Standard for The Format of ARPA Internet Text Messages</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc1808/rfc1808.txt">Relative Uniform Resource Locators</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc1036/rfc1036.txt">Standard for Interchange of USENET Messages</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc977/rfc977.txt">Network News Transfer Protocol</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc2047/rfc2047.txt">MIME (Multipurpose Internet Mail Extensions) Part Three: Message Header Extensions for Non-ASCII Text</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc1867/rfc1867.txt">Form-based File Upload in HTML</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc821/rfc821.txt">Simple Mail Transfer Protocol</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc1590/rfc1590.txt">Media Type Registration Procedure</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc959/rfc959.txt">File Transfer Protocol</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc1700/rfc1700.txt">Assigned Numbers</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc1737/rfc1737.txt">Functional Requirements for Uniform Resource Names</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc1864/rfc1864.txt">The Content-MD5 Header Field</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc1900/rfc1900.txt">Renumbering Needs Work</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc1952/rfc1952.txt">GZIP file format specification version 4.3</a></cite></li>
<li><cite>Improving HTTP Latency</cite></li>
<li><cite><a href="http://www.isi.edu/touch/pubs/http-perf96/">Analysis of HTTP Performance</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc1305/rfc1305.txt">Network Time Protocol (Version 3) Specification, Implementation and Analysis</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc1951/rfc1951.txt">DEFLATE Compressed Data Format Specification version 1.3</a></cite></li>
<li><cite><a href="http://sunsite.unc.edu/mdma-release/http-prob.html">Analysis of HTTP Performance Problems,</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc1950/rfc1950.txt">ZLIB Compressed Data Format Specification version 3.3</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc2069/rfc2069.txt">An Extension to HTTP: Digest Access Authentication</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc2068/rfc2068.txt">Hypertext Transfer Protocol -- HTTP/1.1</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc2119/rfc2119.txt">Key words for use in RFCs to Indicate Requirement Levels</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc1806/rfc1806.txt">Communicating Presentation Information in Internet Messages: The Content-Disposition Header</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc2145/rfc2145.txt">Use and Interpretation of HTTP Version Numbers</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc2076/rfc2076.txt">Common Internet Message Headers</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc2279/rfc2279.txt">UTF-8, a transformation format of Unicode and ISO-10646</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc2046/rfc2046.txt">Multipurpose Internet Mail Extensions (MIME) Part Two: Media Types</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc2277/rfc2277.txt">IETF Policy on Character Sets and Languages</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc2396/rfc2396.txt">Uniform Resource Identifiers (URI): Generic Syntax and Semantics</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc2617/rfc2617.txt">HTTP Authentication: Basic and Digest Access Authentication</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc2110/rfc2110.txt">MIME E-mail Encapsulation of Aggregate Documents, such as HTML (MHTML)</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc2026/rfc2026.txt">The Internet Standards Process -- Revision 3</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc2324/rfc2324.txt">Hyper Text Coffee Pot Control Protocol (HTCPCP/1.0)</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc2049/rfc2049.txt">Multipurpose Internet Mail Extensions (MIME) Part Five: Conformance Criteria and Examples</a></cite></li>
<li><cite><a href="http://rfc.askapache.com/rfc2183/rfc2183.txt">Communicating Presentation Information in Internet Messages: The Content-Disposition Header Field</a></cite></li>
</ul><p><a href="http://www.askapache.com/htaccess/pdf-cookies-headers-rewrites.html"></a><a href="http://www.askapache.com/htaccess/pdf-cookies-headers-rewrites.html">3 Ways to Serve PDF Files using Htaccess Cookies, Headers, Rewrites</a> originally appeared on <cite>AskApache.com</cite> </p>]]></content:encoded>
			<wfw:commentRss>http://www.askapache.com/htaccess/pdf-cookies-headers-rewrites.html/feed</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Htaccess Rewrites &#8211; Rewrite Tricks and Tips</title>
		<link>http://www.askapache.com/htaccess/modrewrite-tips-tricks.html</link>
		<comments>http://www.askapache.com/htaccess/modrewrite-tips-tricks.html#comments</comments>
		<pubDate>Sun, 10 Apr 2011 14:05:00 +0000</pubDate>
		<dc:creator>AskApache</dc:creator>
				<category><![CDATA[Htaccess]]></category>

		<guid isPermaLink="false">http://www.askapache.com/htaccess/mod_rewrite-tips-and-tricks.html</guid>
		<description><![CDATA[<p><strong>htaccess rewrite</strong> / Mod_Rewrite Tips and Tricks is as glamorous as it sounds!  htaccess rewrite mod_rewrite is just possibly one of the most useful Apache modules and features.  The ability to rewrite requests internally as well as externally is extremely powerful.</p>
<p><a class="hs hs13" href="http://www.askapache.com/htaccess/mod_rewrite-tips-and-tricks.html"></a></p>]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.askapache.com/htaccess/modrewrite-tips-tricks.html"></a><a href="http://www.askapache.com/htaccess/modrewrite-tips-tricks.html"><cite>AskApache.com</cite></a></p><p><strong>Htaccess Rewrites</strong> are enabled by using the Apache module <a href="http://www.askapache.com/servers/mod_rewrite.c.html">mod_rewrite</a>, which is one of the most powerful Apache modules and features availale.  Htaccess Rewrites through mod_rewrite provide the special ability to <strong>Rewrite requests internally</strong> as well as <em>Redirect request externally</em>.<br class="C" /></p>
<p><a class="hs hs13" href="http://www.askapache.com/servers/mod_rewrite.c.html"></a></p>

<p>When the url in your browser's location bar stays the same for a request it is an internal rewrite, when the url changes an external redirection is taking place.  This is one of the first, and one of the biggest mental-blocks people have when learning about mod_rewrite...  But I have a secret weapon for you to use, a new discovery from years of research that makes learning mod_rewrite drastically quicker and easier.  It truly does or I wouldn't be saying so in the introduction of this article.</p>

<blockquote><p>Despite the tons of examples and docs, <strong>mod_rewrite is voodoo</strong>.
Damned cool voodoo, but still voodoo.<br />-- <cite>Brian Moore</cite></p></blockquote>

<p class="anote"><strong>Note:</strong>  After years of fighting to learn my way through rewriting urls with mod_rewrite, I finally had a breakthrough and found a way to outsmart the difficulty of mod_rewrite that I just couldn't seem to master.  The <a href="http://www.askapache.com/htaccess/mod_rewrite-variables-cheatsheet.html">Mod_Rewrite RewriteCond/RewriteRule Variable Value Cheatsheet</a> is the one-of-a-kind tool that changed the game for me and made mod_rewriting no-harder than anything else.</p>

<p>So keep that mod_rewrite reference bookmarked and you will be able to figure out any RewriteRule or RewriteCond, an amazing feat considering it took me a LONG time to figure this stuff out on my own.  But that was before <a href="http://www.askapache.com/htaccess/crazy-advanced-mod_rewrite-tutorial.html">the craziness</a>, one of the most challenging and productive .htaccess experiments I've done... An experiment so <strong>ILL</strong> it's sick like a diamond disease on your wrist! $$$.  That mod_rewrite experiment/tutorial was the culmination of many different advanced mod_rewrite experiments I had done in the past and included most of my very best .htaccess tricks.  With the cheatsheet it's no longer Voodoo.. Its just what you do.  Now lets dig in!</p>



<h2>Htaccess rewrites TOC</h2>
        <ul>
            <li><a href="#default-mod-rewrite-hint" title=".htaccess mod rewrite should use Options +FollowSymLinks">.htaccess rewrite examples should begin with:</a></li>
            <li><a href="#require-the-www-in-htaccess" title="Use mod_rewrite in Apache htaccess to Require the www for SEO">Require the www</a></li>
            <li><a href="#require-no-www-in-htaccess" title="Use mod_rewrite in Apache htaccess to Require no www for SEO">Require no www</a></li>
            <li><a href="#check-for-key-in-query-string" title="Search for a key in the query string">Check for a key in QUERY_STRING</a></li>
            <li><a href="#delete-query-string" title="Remove the query string from url">Removes the QUERY_STRING from the URL</a></li>
            <li><a href="#fix-infinite-loop-redirects" title="Stop internal redirect looping">Fix for infinite loops</a></li>
            <li><a href="#external-redirect-php-files-to-html" title="Redirecting .php file extensions to .html">Redirect .php files to .html files (SEO friendly)</a></li>
            <li><a href="#internal-redirect-php-files-to-html" title="Redirecting .html file extensions to .php">Redirect .html files to actual .php files (SEO friendly)</a></li>
            <li><a href="#time-based-access" title="Deny access with Apache htaccess during certain hours of the day">block access to files during certain hours of the day</a></li>
            <li><a href="#convert-underscore-hyphen" title="Change underscores to hyphens for SEO URL">Rewrite underscores to hyphens for SEO URL</a></li>
            <li><a href="#require-www-no-hardcoding" title="mod_rewrite example of SEO 301 redirecting non-www to www">Require the www without hardcoding</a></li>
            <li><a href="#require-no-subdomain-1" title="mod_rewrite subdomain usage example of SEO 301 redirecting">Require no subdomain</a></li>
            <li><a href="#require-no-subdomain-2" title="Apache htaccess htaccess rewrite ~without slash">Require no subdomain</a></li>
            <li><a href="#redirect-wordpress-feed" title="Rewriting WordPress RSS feeds to Feedburner in SEO friendly method">Redirecting WordPress Feeds to Feedburner</a></li>
            <li><a href="#only-allow-get-and-put-requests" title="Deny Request Methods other than GET or PUT">Only allow GET and PUT request methods</a></li>
            <li><a href="#prevent-hotlinking" title="hotlinking and bandwidth stealing with mod_rewrite, hotlinking example">Prevent Files image/file hotlinking and bandwidth stealing</a></li>
            <li><a href="#stop-browser-prefetching" title="Fix prefetching in browsers">Stop browser prefetching</a></li>
        </ul>

<hr />

<p>If you really want to take a look, check out the <a href="http://www.askapache.com/servers/mod_rewrite.c.html">mod_rewrite.c</a> and <a href="http://www.askapache.com/servers/mod_rewrite.h.html">mod_rewrite.h</a> files.</p>

<p>Be aware that mod_rewrite (<em>RewriteRule, RewriteBase, and RewriteCond</em>) code is executed for each and every HTTP request that accesses a file in or below the directory where the code resides, so it's always good to limit the code to certain circumstances if readily identifiable.</p>
<p><strong>For example</strong>, to limit the next 5 RewriteRules to only be applied to .html and .php files, you can use the following code, which tests if the url does not end in .html or .php and if it doesn't, it will skip the next 5 RewriteRules.</p><hr />
<pre>RewriteRule !\.(html|php)$ - [S=5]
RewriteRule ^.*-(vf12|vf13|vf5|vf35|vf1|vf10|vf33|vf8).+$ - [S=1]</pre>

<h2><a href="#default-mod-rewrite-hint" name="default-mod-rewrite-hint" id="default-mod-rewrite-hint" title="Mostly .htaccess rewrite examples should begin with:" class="acd">.htaccess rewrite examples should begin with:</a></h2>
<pre>Options +FollowSymLinks
&nbsp;
RewriteEngine On
RewriteBase /</pre>


<h2><a href="#require-the-www-in-htaccess" name="require-the-www-in-htaccess" id="require-the-www-in-htaccess" title="Require the www" class="acd">Require the www</a></h2>
<pre>Options +FollowSymLinks
RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_HOST} !^www\.askapache\.com$ [NC]
RewriteRule ^(.*)$ http://www.askapache.com/$1 [R=301,L]</pre>


<h2>Loop Stopping Code</h2>
<p>Sometimes your rewrites cause infinite loops, stop it with one of these rewrite code snippets.</p>
<pre>RewriteCond %{REQUEST_URI} ^/(stats/|missing\.html|failed_auth\.html|error/).* [NC]
RewriteRule .* - [L]
&nbsp;
RewriteCond %{ENV:REDIRECT_STATUS} 200
RewriteRule .* - [L]</pre>

<h2>Cache-Friendly File Names</h2>
<p>This is probably my favorite, and I use it on every site I work on.  It allows me to update my javascript and css files in my visitors cache's simply by naming them differently in the html, on the server they stay the same name.  This rewrites all files for <code>/zap/j/anything-anynumber.js to /zap/j/anything.js and /zap/c/anything-anynumber.css to /zap/c/anything.css</code></p>
<pre>RewriteRule ^zap/(j|c)/([a-z]+)-([0-9]+)\.(js|css)$ /zap/$1/$2.$4 [L]</pre>




<h2>SEO friendly link for non-flash browsers</h2>
<p>When you use flash on your site and you properly supply a link to download flash that shows up for non-flash aware browsers, it is nice to use a shortcut to keep your code clean and your external links to a minimum.  This code allows me to link to <code>site.com/getflash/</code> for non-flash aware browsers.</p>
<pre>RewriteRule ^getflash/?$ http://www.adobe.com/shockwave/download/download.cgi?P1_Prod_Version=ShockwaveFlash [NC,L,R=307]</pre>

<h2>Removing the Query_String</h2>
<p>On many sites, the page will be displayed for both page.html and page.html?anything=anything, which hurts your SEO with duplicate content.  An easy way to fix this issue is to redirect external requests containing a query string to the same uri without the query_string.</p>
<pre>RewriteCond %{THE_REQUEST} ^GET\ /.*\;.*\ HTTP/
RewriteCond %{QUERY_STRING} !^$
RewriteRule .* http://www.askapache.com%{REQUEST_URI}? [R=301,L]</pre>


<h2>Sending requests to a php script</h2>
<p>This .htaccess rewrite example invisibly rewrites requests for all Adobe pdf files to be handled by <code>/cgi-bin/pdf-script.php</code></p>
<pre>RewriteRule ^(.+)\.pdf$  /cgi-bin/pdf-script.php?file=$1.pdf [L,NC,QSA]</pre>


<h2>Setting the language variable based on Client</h2>
<p>For sites using multiviews or with multiple language capabilities, it is nice to be able to send the correct language automatically based on the clients preferred language.</p>
<pre>RewriteCond %{HTTP:Accept-Language} ^.*(de|es|fr|it|ja|ru|en).*$ [NC]
RewriteRule ^(.*)$ - [env=prefer-language:%1]</pre>



<h2>Deny Access To Everyone Except PHP fopen</h2>
<p>This allows access to all files by php fopen, but denies anyone else.</p>
<pre>RewriteEngine On
RewriteBase /
RewriteCond %{THE_REQUEST} ^.+$ [NC]
RewriteRule .* - [F,L]</pre>


<p class="cnote">If you are looking for ways to block or deny specific requests/visitors, then you should definately read <a href="http://perishablepress.com/press/2009/02/03/eight-ways-to-blacklist-with-apaches-mod_rewrite/" title="Eight Ways to Blacklist with Apache’s mod_rewrite">Blacklist with mod_rewrite</a>.  I give it a 10/10</p>


<h2>Deny access to anything in a subfolder except php fopen</h2>
<p>This can be very handy if you want to serve media files or special downloads but only through a php proxy script.</p>
<pre>RewriteEngine On
RewriteBase /
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /([^/]+)/.*\ HTTP [NC]
RewriteRule .* - [F,L]</pre>





<h2><a href="#require-no-www-in-htaccess" name="require-no-www-in-htaccess" id="require-no-www-in-htaccess" title="Require no www" class="acd">Require no www</a></h2>
<pre>Options +FollowSymLinks
RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_HOST} !^askapache\.com$ [NC]
RewriteRule ^(.*)$ http://askapache.com/$1 [R=301,L]</pre>


<h2><a href="#check-for-key-in-query-string" name="check-for-key-in-query-string" id="check-for-key-in-query-string" title="Search for a key in the query string" class="acd">Check for a key in QUERY_STRING</a></h2>
<p>Uses a <a href="http://askapache.info/trunk/mod/mod_rewrite.html#rewritecond" title="RewriteCond Directive Use in htaccess">RewriteCond</a> Directive to check QUERY_STRING for passkey, if it doesn't find it it redirects all requests for anything in the /logged-in/ directory to the /login.php script.</p>
<pre>RewriteEngine On
RewriteBase /
RewriteCond %{QUERY_STRING} !passkey
RewriteRule ^/logged-in/(.*)$ /login.php [L]</pre>


<h2><a href="#delete-query-string" name="delete-query-string" id="delete-query-string" title="Remove the query string from url" class="acd">Removes the QUERY_STRING from the URL</a></h2>
<p>If the QUERY_STRING has any value at all besides blank than the<code>?</code>at the end of /login.php? tells mod_rewrite to remove the QUERY_STRING from login.php and redirect.</p>
<pre>RewriteEngine On
RewriteBase /
RewriteCond %{QUERY_STRING} .
RewriteRule ^login.php /login.php? [L]</pre>


<h2><a href="#fix-infinite-loop-redirects" name="fix-infinite-loop-redirects" id="fix-infinite-loop-redirects" title="Fix for infinite loops" class="acd">Fix for infinite loops</a></h2>
<p>An error message related to this is<code>Request exceeded the limit of 10 internal redirects due to probable configuration error. Use &#039;LimitInternalRecursion&#039; to increase the limit if necessary. Use &#039;LogLevel debug&#039; to get a backtrace.</code>or you may see<code>Request exceeded the limit</code>,<code>probable configuration error</code>,<code>Use &#039;LogLevel debug&#039; to get a backtrace</code>, or<code>Use &#039;LimitInternalRecursion&#039; to increase the limit if necessary</code></p>
<pre>RewriteCond %{ENV:REDIRECT_STATUS} 200
RewriteRule .* - [L]</pre>


<h2><a href="#external-redirect-php-files-to-html" name="external-redirect-php-files-to-html" id="external-redirect-php-files-to-html" title="External Redirect .php files to .html files (SEO friendly)" class="acd">External Redirect .php files to .html files (SEO friendly)</a></h2>
<pre>RewriteRule ^(.*)\.php$ /$1.html [R=301,L]</pre>


<h2><a href="#internal-redirect-php-files-to-html" name="internal-redirect-php-files-to-html" id="internal-redirect-php-files-to-html" title="Internal Redirect .php files to .html files (SEO friendly)" class="acd">Internal Redirect .php files to .html files (SEO friendly)</a></h2>
<p>Redirects all files that end in .html to be served from filename.php  so it looks like all your pages are .html but really they are .php</p>
<pre>RewriteRule ^(.*)\.html$ $1.php [R=301,L]</pre>


<h2><a href="#time-based-access" name="time-based-access" id="time-based-access" title="block access to files during certain hours of the day" class="acd">block access to files during certain hours of the day</a></h2>
<pre>Options +FollowSymLinks
RewriteEngine On
RewriteBase /
# If the hour is 16 (4 PM) Then deny all access
RewriteCond %{TIME_HOUR} ^16$
RewriteRule ^.*$ - [F,L]</pre>


<h2><a href="#convert-underscore-hyphen" name="convert-underscore-hyphen" id="convert-underscore-hyphen" title="Change underscores to hyphens for SEO URL" class="acd">Rewrite underscores to hyphens for SEO URL</a></h2>
<p>Converts all underscores "_" in urls to hyphens "-" for SEO benefits...  See the <a href="http://www.askapache.com/htaccess/rewrite-underscores-to-hyphens-for-seo-url.html">full article</a> for more info.</p>
<pre>Options +FollowSymLinks
RewriteEngine On
RewriteBase /
&nbsp;
RewriteRule !\.(html|php)$ - [S=4]
RewriteRule ^([^_]*)_([^_]*)_([^_]*)_([^_]*)_(.*)$ $1-$2-$3-$4-$5 [E=uscor:Yes]
RewriteRule ^([^_]*)_([^_]*)_([^_]*)_(.*)$ $1-$2-$3-$4 [E=uscor:Yes]
RewriteRule ^([^_]*)_([^_]*)_(.*)$ $1-$2-$3 [E=uscor:Yes]
RewriteRule ^([^_]*)_(.*)$ $1-$2 [E=uscor:Yes]
&nbsp;
RewriteCond %{ENV:uscor} ^Yes$
RewriteRule (.*) http://d.com/$1 [R=301,L]</pre>


<h2><a href="#require-www-no-hardcoding" name="require-www-no-hardcoding" id="require-www-no-hardcoding" title="Require the www without hardcoding" class="acd">Require the www without hardcoding</a></h2>
<pre>Options +FollowSymLinks
RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_HOST} !^www\.[a-z-]+\.[a-z]{2,6} [NC]
RewriteCond %{HTTP_HOST} ([a-z-]+\.[a-z]{2,6})$     [NC]
RewriteRule ^/(.*)$ http://%1/$1 [R=301,L]</pre>


<h2><a href="#require-no-subdomain-1" name="require-no-subdomain-1" id="require-no-subdomain-1" title="Require no subdomain" class="acd">Require no subdomain</a></h2>
<pre>RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_HOST} \.([a-z-]+\.[a-z]{2,6})$ [NC]
RewriteRule ^/(.*)$ http://%1/$1 [R=301,L]</pre>


<h2><a href="#require-no-subdomain-2" name="require-no-subdomain-2" id="require-no-subdomain-2" title="Require no subdomain" class="acd">Require no subdomain</a></h2>
<pre>RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_HOST} \.([^\.]+\.[^\.0-9]+)$
RewriteRule ^(.*)$ http://%1/$1 [R=301,L]</pre>


<h2><a href="#redirect-wordpress-feed" name="redirect-wordpress-feed" id="redirect-wordpress-feed" title="Redirecting WordPress Feeds to Feedburner" class="acd">Redirecting WordPress Feeds to Feedburner</a></h2>
<p>Full article:<a href="http://www.askapache.com/htaccess/redirecting-wordpress-feeds-to-feedburner.html" title="Redirecting WordPress Feeds to Feedburner">Redirecting WordPress Feeds to Feedburner</a></p>
<pre>RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_URI} ^/feed\.gif$
RewriteRule .* - [L]
&nbsp;
RewriteCond %{HTTP_USER_AGENT} !^.*(FeedBurner|FeedValidator) [NC]
RewriteRule ^feed/?.*$ http://feeds.feedburner.com/apache/htaccess [L,R=302]
&nbsp;
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]</pre>


<h2><a href="#only-allow-get-and-put-requests" name="only-allow-get-and-put-requests" id="only-allow-get-and-put-requests" title="Only allow GET and PUT request methods" class="acd">Only allow GET and PUT Request Methods</a></h2>
<p>Article: <a class="acd" href="http://www.askapache.com/htaccess/apache-status-code-headers-errordocument.html#http-methods-recognized" title="List of Apache Recognized Request Methods">Request Methods</a></p>
<pre>RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_METHOD} !^(GET|PUT)
RewriteRule .* - [F]</pre>


<h2><a href="#prevent-hotlinking" name="prevent-hotlinking" id="prevent-hotlinking" title="Prevent Files image/file hotlinking and bandwidth stealing" class="acd">Prevent Files image/file hotlinking and bandwidth stealing</a></h2>
<pre>RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^http://(www\.)?askapache.com/.*$ [NC]
RewriteRule \.(gif|jpg|swf|flv|png)$ /feed/ [R=302,L]</pre>


<h2><a href="#stop-browser-prefetching" name="stop-browser-prefetching" id="stop-browser-prefetching" title="Stop browser prefetching" class="acd">Stop browser prefetching</a></h2>
<pre>RewriteEngine On
SetEnvIfNoCase X-Forwarded-For .+ proxy=yes
SetEnvIfNoCase X-moz prefetch no_access=yes
&nbsp;
# block pre-fetch requests with X-moz headers
RewriteCond %{ENV:no_access} yes
RewriteRule .* - [F,L]</pre>



<blockquote cite="http://askapache.info/trunk/mod/mod_rewrite.html#rewritebase">
<p>This module uses a rule-based rewriting engine (based on a regular-expression parser) to rewrite requested URLs on the fly. It supports an unlimited number of rules and an unlimited number of attached rule conditions for each rule, to provide a really flexible and powerful URL manipulation mechanism. The URL manipulations can depend on various tests, of server variables, environment variables, HTTP headers, or time stamps. Even external database lookups in various formats can be used to achieve highly granular URL matching.</p>
<p>This module operates on the full URLs (including the path-info part) both in per-server context (<code>httpd.conf</code>) and per-directory context (<code>.htaccess</code>) and can generate query-string parts on result. The rewritten result can lead to internal sub-processing, external request redirection or even to an internal proxy throughput.</p>
<p>Further details, discussion, and examples, are provided in the <a href="http://askapache.info/trunk/rewrite/index.html">detailed mod_rewrite documentation</a>.</p>
</blockquote>
<h2>Directives</h2>
<ul>
    <li><a href="http://askapache.info/trunk/mod/mod_rewrite.html#rewritebase">RewriteBase</a></li>
    <li><a href="http://askapache.info/trunk/mod/mod_rewrite.html#rewritecond">RewriteCond</a></li>
    <li><a href="http://askapache.info/2.2/mod/mod_rewrite.html#rewriteengine">RewriteEngine</a></li>
    <li><a href="http://askapache.info/trunk/mod/mod_rewrite.html#rewritelock">RewriteLock</a></li>
    <li><a href="http://askapache.info/2.0/mod/mod_rewrite.html#rewritelog">RewriteLog</a></li>
    <li><a href="http://askapache.info/trunk/mod/mod_rewrite.html#rewriteloglevel">RewriteLogLevel</a></li>
    <li><a href="http://askapache.info/trunk/mod/mod_rewrite.html#rewritemap">RewriteMap</a></li>
    <li><a href="http://askapache.info/1.3/mod/mod_rewrite.html#rewriteoptions">RewriteOptions</a></li>
    <li><a href="http://askapache.info/trunk/mod/mod_rewrite.html#rewriterule">RewriteRule</a></li>
</ul>



<p>If you aren't already comfortable using mod_rewrite then I recommend this <a href="http://check-these.info/mod_rewrite-basic.html">excellent mod_rewrite guide</a> by one of my favorite mod_rewrite gurus that I've met.</p>



<hr />
<h2>htaccess Guide Sections</h2>
<ul class="ou">
    <li><a rel="chapter bookmark" href="http://www.askapache.com/htaccess/htaccess-for-webmasters.html" title="Apache HTTP Web Server htaccess tips and tricks">htaccess tricks for Webmasters</a></li>
    <li><a rel="chapter bookmark" href="http://www.askapache.com/htaccess/using-http-headers-with-htaccess.html" title="Creating and using HTTP Headers with htaccess">HTTP Header control with htaccess</a></li>
    <li><a rel="chapter bookmark" href="http://www.askapache.com/htaccess/php-htaccess-tips-and-tricks.html" title="mod_php or php as a cgi with htaccess tips, htaccess php tricks">PHP on Apache tips and tricks</a></li>
    <li><a rel="chapter bookmark" href="http://www.askapache.com/htaccess/seo-search-engine-friendly-redirects-without-mod_rewrite.html" title="SEO-Friendly 301 Redirects without mod_rewrite">SEO Redirects without mod_rewrite</a></li>
    <li><a rel="chapter bookmark" href="http://www.askapache.com/htaccess/mod_rewrite-tips-and-tricks.html" title="mod_rewrite tips and tricks with RewriteEngine, RewriteBase, RewriteRule, and RewriteCond">mod_rewrite examples, tips, and tricks</a></li>
    <li><a rel="chapter bookmark" href="http://www.askapache.com/htaccess/speed-up-your-site-with-caching-and-cache-control.html" title="Caching, cache-control, cache, expires, and optimizing htaccess">HTTP Caching and Site Speedups</a></li>
    <li><a rel="chapter bookmark" href="http://www.askapache.com/htaccess/apache-authentication-in-htaccess.html" title="htaccess and Apache authentication with htpasswd, 401, and 403">Authentication on Apache</a></li>
    <li><a rel="chapter bookmark" href="http://www.askapache.com/htaccess/security-with-htaccess.html" title="Security, hacking, and anti-hacking tips and tricks for htaccess">htaccess Security Tricks and Tips</a></li>
    <li><a rel="chapter bookmark" href="http://www.askapache.com/htaccess/ssl-example-usage-in-htaccess.html" title="Apache SSL examples">SSL tips and examples</a></li>
    <li><a rel="chapter bookmark" href="http://www.askapache.com/htaccess/apache-variable-fun-in-htaccess.html" title="Apache variables info, tricks, and tips">Variable Fun (mod_env) Section</a></li><li><a rel="chapter bookmark" href="http://www.askapache.com/htaccess/mod_security-htaccess-tricks.html" title="mod_security Guide and sample mod_Security diretive usage in .htaccess">.htaccess Security with MOD_SECURITY</a></li><li><a rel="chapter bookmark" href="http://www.askapache.com/htaccess/setenvif.html" title="SetEnvIf and SetEnvIfNoCase Examples for conditionally setting variables in Apache .htaccess">SetEnvIf and SetEnvIfNoCase Examples</a></li>
</ul>


<p class="ment"><a rel="prev" href="http://www.askapache.com/htaccess/seo-search-engine-friendly-redirects-without-mod_rewrite.html" title="Use htaccess to create SEO-Friendly 301 Redirects without mod_rewrite">&laquo;  Search Engine Friendly Redirects</a> | <a href="http://www.askapache.com/htaccess/htaccess.html" class="acd1" rel="Contents Index Start" title=".htaccess tutorial">.htaccess Tutorial Index</a> | <a rel="next" href="http://www.askapache.com/htaccess/speed-up-your-site-with-caching-and-cache-control.html" title="The Apache method for speeding up sites with Caching, cache-control, cache, expires, and optimizing htaccess">&raquo;  Speed up your site with Caching and cache-control</a></p><p><a href="http://www.askapache.com/htaccess/modrewrite-tips-tricks.html"></a><a href="http://www.askapache.com/htaccess/modrewrite-tips-tricks.html">Htaccess Rewrites &#8211; Rewrite Tricks and Tips</a> originally appeared on <cite>AskApache.com</cite> </p>]]></content:encoded>
			<wfw:commentRss>http://www.askapache.com/htaccess/modrewrite-tips-tricks.html/feed</wfw:commentRss>
		<slash:comments>128</slash:comments>
		</item>
		<item>
		<title>PHP to handle HTTP Status Codes for ErrorDocument</title>
		<link>http://www.askapache.com/php/php-errordocument.html</link>
		<comments>http://www.askapache.com/php/php-errordocument.html#comments</comments>
		<pubDate>Fri, 19 Nov 2010 04:03:22 +0000</pubDate>
		<dc:creator>AskApache</dc:creator>
				<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.askapache.com/?p=4783</guid>
		<description><![CDATA[<p>Fast, HTTP Protocol, protection.  If you are reading this article, you already know enough about the benefits of making sure your site can handle HTTP Protocol Errors.  This is a nice single php file with no dependencies or requirements, will work on anything.  Optimized for minimizing bandwidth and resource-hogging connections from bots and spambots.</p>
<pre>
<?php
ob_start();
@set_time_limit(5);
@ini_set('memory_limit', '64M');
@ini_set('display_errors', 'Off');
error_reporting(0);
</pre>]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.askapache.com/php/php-errordocument.html"></a><a href="http://www.askapache.com/php/php-errordocument.html"><cite>AskApache.com</cite></a></p><p>The php part of this article is based on my <a href="http://www.askapache.com/wordpress/wordpress-404.html">Advanced WordPress 404.php</a> article from 2008.  Many of the following ideas came out of the research performed to enumerate <a href="http://www.askapache.com/htaccess/apache-status-code-headers-errordocument.html">every single Apache ErrorDocument</a>, including learning how to view the defaults and many cool tricks for htaccess.</p>



<h2>The PHP HTTP ErrorDocument Handler</h2>
<p>Just save this as <code>/err.php</code> or whatever.  The best is to put it in a cgi-bin script-alias directory under your DOCUMENT_ROOT like <code>/cgi-bin/e.php</code> but most people don't know how.  That way you can setup some advanced stuff in a <code>/cgi-bin/.htaccess</code> file.  If you are interested in locking it down, I recommend reading <a href="http://www.askapache.com/htaccess/php-cgi-redirect_status.html">Securing php.ini and php-cgi with .htaccess</a>.</p>


<h2>Advantages and Reasons for Using</h2>
<p>Fast, HTTP Protocol Compliance, protection.  If you are reading this article, you already know and just want to check out the code!</p>



<pre>&lt;?php
ob_start();
@set_time_limit(5);
@ini_set(&#039;memory_limit&#039;, &#039;64M&#039;);
@ini_set(&#039;display_errors&#039;, &#039;Off&#039;);
error_reporting(0);
&nbsp;
function print_error_page()
{
&nbsp;
  $status_reason = array(
  100 =&gt; &#039;Continue&#039;,
  101 =&gt; &#039;Switching Protocols&#039;,
  102 =&gt; &#039;Processing&#039;,
  200 =&gt; &#039;OK&#039;,
  201 =&gt; &#039;Created&#039;,
  202 =&gt; &#039;Accepted&#039;,
  203 =&gt; &#039;Non-Authoritative Information&#039;,
  204 =&gt; &#039;No Content&#039;,
  205 =&gt; &#039;Reset Content&#039;,
  206 =&gt; &#039;Partial Content&#039;,
  207 =&gt; &#039;Multi-Status&#039;,
  226 =&gt; &#039;IM Used&#039;,
  300 =&gt; &#039;Multiple Choices&#039;,
  301 =&gt; &#039;Moved Permanently&#039;,
  302 =&gt; &#039;Found&#039;,
  303 =&gt; &#039;See Other&#039;,
  304 =&gt; &#039;Not Modified&#039;,
  305 =&gt; &#039;Use Proxy&#039;,
  306 =&gt; &#039;Reserved&#039;,
  307 =&gt; &#039;Temporary Redirect&#039;,
  400 =&gt; &#039;Bad Request&#039;,
  401 =&gt; &#039;Unauthorized&#039;,
  402 =&gt; &#039;Payment Required&#039;,
  403 =&gt; &#039;Forbidden&#039;,
  404 =&gt; &#039;Not Found&#039;,
  405 =&gt; &#039;Method Not Allowed&#039;,
  406 =&gt; &#039;Not Acceptable&#039;,
  407 =&gt; &#039;Proxy Authentication Required&#039;,
  408 =&gt; &#039;Request Timeout&#039;,
  409 =&gt; &#039;Conflict&#039;,
  410 =&gt; &#039;Gone&#039;,
  411 =&gt; &#039;Length Required&#039;,
  412 =&gt; &#039;Precondition Failed&#039;,
  413 =&gt; &#039;Request Entity Too Large&#039;,
  414 =&gt; &#039;Request-URI Too Long&#039;,
  415 =&gt; &#039;Unsupported Media Type&#039;,
  416 =&gt; &#039;Requested Range Not Satisfiable&#039;,
  417 =&gt; &#039;Expectation Failed&#039;,
  422 =&gt; &#039;Unprocessable Entity&#039;,
  423 =&gt; &#039;Locked&#039;,
  424 =&gt; &#039;Failed Dependency&#039;,
  426 =&gt; &#039;Upgrade Required&#039;,
  500 =&gt; &#039;Internal Server Error&#039;,
  501 =&gt; &#039;Not Implemented&#039;,
  502 =&gt; &#039;Bad Gateway&#039;,
  503 =&gt; &#039;Service Unavailable&#039;,
  504 =&gt; &#039;Gateway Timeout&#039;,
  505 =&gt; &#039;HTTP Version Not Supported&#039;,
  506 =&gt; &#039;Variant Also Negotiates&#039;,
  507 =&gt; &#039;Insufficient Storage&#039;,
  510 =&gt; &#039;Not Extended&#039;
  );
&nbsp;
  $status_msg = array(
  400 =&gt; "Your browser sent a request that this server could not understand.",
  401 =&gt; "This server could not verify that you are authorized to access the document requested.",
  402 =&gt; &#039;The server encountered an internal error or misconfiguration and was unable to complete your request.&#039;,
  403 =&gt; "You don&#039;t have permission to access %U% on this server.",
  404 =&gt; "We couldn&#039;t find &lt;acronym title=&#039;%U%&#039;&gt;that uri&lt;/acronym&gt; on our server, though it&#039;s most certainly not your fault.",
  405 =&gt; "The requested method is not allowed for the URL %U%.",
  406 =&gt; "An appropriate representation of the requested resource %U% could not be found on this server.",
  407 =&gt; "An appropriate representation of the requested resource %U% could not be found on this server.",
  408 =&gt; "Server timeout waiting for the HTTP request from the client.",
  409 =&gt; &#039;The server encountered an internal error or misconfiguration and was unable to complete your request.&#039;,
  410 =&gt; "The requested resource %U% is no longer available on this server and there is no forwarding address. Please remove all references to this resource.",
  411 =&gt; "A request of the requested method GET requires a valid Content-length.",
  412 =&gt; "The precondition on the request for the URL %U% evaluated to false.",
  413 =&gt; "The requested resource %U% does not allow request data with GET requests, or the amount of data provided in the request exceeds the capacity limit.",
  414 =&gt; "The requested URL&#039;s length exceeds the capacity limit for this server.",
  415 =&gt; "The supplied request data is not in a format acceptable for processing by this resource.",
  416 =&gt; &#039;Requested Range Not Satisfiable&#039;,
  417 =&gt; "The expectation given in the Expect request-header field could not be met by this server. The client sent &lt;code&gt;Expect:&lt;/code&gt;",
  422 =&gt; "The server understands the media type of the request entity, but was unable to process the contained instructions.",
  423 =&gt; "The requested resource is currently locked. The lock must be released or proper identification given before the method can be applied.",
  424 =&gt; "The method could not be performed on the resource because the requested action depended on another action and that other action failed.",
  425 =&gt; &#039;The server encountered an internal error or misconfiguration and was unable to complete your request.&#039;,
  426 =&gt; "The requested resource can only be retrieved using SSL. Either upgrade your client, or try requesting the page using https://",
  500 =&gt; &#039;The server encountered an internal error or misconfiguration and was unable to complete your request.&#039;,
  501 =&gt; "This type of request method to %U% is not supported.",
  502 =&gt; "The proxy server received an invalid response from an upstream server.",
  503 =&gt; "The server is temporarily unable to service your request due to maintenance downtime or capacity problems. Please try again later.",
  504 =&gt; "The proxy server did not receive a timely response from the upstream server.",
  505 =&gt; &#039;The server encountered an internal error or misconfiguration and was unable to complete your request.&#039;,
  506 =&gt; "A variant for the requested resource &lt;code&gt;%U%&lt;/code&gt; is itself a negotiable resource. This indicates a configuration error.",
  507 =&gt; "The method could not be performed.  There is insufficient free space left in your storage allocation.",
  510 =&gt; "A mandatory extension policy in the request is not accepted by the server for this resource."
  );
&nbsp;
  // Get the Status Code
  if (isset($_SERVER[&#039;REDIRECT_STATUS&#039;]) &amp;&amp; ($_SERVER[&#039;REDIRECT_STATUS&#039;] != 200))$sc = $_SERVER[&#039;REDIRECT_STATUS&#039;];
  elseif (isset($_SERVER[&#039;REDIRECT_REDIRECT_STATUS&#039;]) &amp;&amp; ($_SERVER[&#039;REDIRECT_REDIRECT_STATUS&#039;] != 200)) $sc = $_SERVER[&#039;REDIRECT_REDIRECT_STATUS&#039;];
  $sc = (!isset($_GET[&#039;error&#039;]) ? 404 : $_GET[&#039;error&#039;]);
&nbsp;
  $sc=abs(intval($sc));
&nbsp;
  // Redirect to server home if called directly or if status is under 400
  if( ( (isset($_SERVER[&#039;REDIRECT_STATUS&#039;]) &amp;&amp; $_SERVER[&#039;REDIRECT_STATUS&#039;] == 200) &amp;&amp; (floor($sc / 100) == 3) )
     || (!isset($_GET[&#039;error&#039;]) &amp;&amp; $_SERVER[&#039;REDIRECT_STATUS&#039;] == 200)  )
  {
      @header("Location: http://{$_SERVER[&#039;SERVER_NAME&#039;]}",1,302);
      die();
  }
&nbsp;
  // Check range of code or issue 500
  if (($sc &lt; 200) || ($sc &gt; 599)) $sc = 500;
&nbsp;
  // Check for valid protocols or else issue 505
  if (!in_array($_SERVER["SERVER_PROTOCOL"], array(&#039;HTTP/1.0&#039;,&#039;HTTP/1.1&#039;,&#039;HTTP/0.9&#039;))) $sc = 505;
&nbsp;
  // Get the status reason
  $reason = (isset($status_reason[$sc]) ? $status_reason[$sc] : &#039;&#039;);
&nbsp;
  // Get the status message
  $msg = (isset($status_msg[$sc]) ? str_replace(&#039;%U%&#039;, htmlspecialchars(strip_tags(stripslashes($_SERVER[&#039;REQUEST_URI&#039;]))), $status_msg[$sc]) : &#039;Error&#039;);
&nbsp;
  // issue optimized headers (optimized for your server)
  @header("{$_SERVER[&#039;SERVER_PROTOCOL&#039;]} {$sc} {$reason}", 1, $sc);
  if( @php_sapi_name() != &#039;cgi-fcgi&#039; ) @header("Status: {$sc} {$reason}", 1, $sc);
&nbsp;
  // A very small footprint for certain types of 4xx class errors and all 5xx class errors
  if (in_array($sc, array(400, 403, 405)) || (floor($sc / 100) == 5))
  {
    @header("Connection: close", 1);
    if ($sc == 405) @header(&#039;Allow: GET,HEAD,POST,OPTIONS&#039;, 1, 405);
  }
&nbsp;
  echo "&lt;!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\"&gt;\n&lt;html&gt;";
  echo "&lt;head&gt;\n&lt;title&gt;{$sc} {$reason}&lt;/title&gt;\n&lt;h1&gt;{$reason}&lt;/h1&gt;\n&lt;p&gt;{$msg}&lt;br /&gt;\n&lt;/p&gt;\n";
}
&nbsp;
function askapache_global_debug()
{
  # http://www.php.net/manual/en/function.array-walk.php#100681
  global $_GET,$_POST,$_ENV,$_SERVER;  $g=array(&#039;_ENV&#039;,&#039;_SERVER&#039;,&#039;_GET&#039;,&#039;_POST&#039;);
  array_walk_recursive($g, create_function(&#039;$n&#039;,&#039;global $$n;if( !!$$n&amp;&amp;ob_start()&amp;&amp;(print "[ $"."$n ]\n")&amp;&amp;array_walk($$n,
    create_function(\&#039;$v,$k\&#039;, \&#039;echo "[$k] =&gt; $v\n";\&#039;))) echo "&lt;"."p"."r"."e&gt;".htmlspecialchars(ob_get_clean())."&lt;"."/"."pr"."e&gt;";&#039;) );
}
&nbsp;
print_error_page();
//if($_SERVER[&#039;REMOTE_ADDR&#039;]==&#039;youripaddress&#039;)askapache_global_debug();
echo "&lt;/body&gt;\n&lt;/html&gt;";
echo ob_get_clean();
exit;
?&gt;</pre>



<p class="bnote"><strong>Note:</strong> If you are installing this on a non-linux/non-apache machine/server, you will need to read your products documentation for custom error documents.  It will work on any machine that can run php.</p>


<h2>Htaccess ErrorDocument Tips</h2>
<p>The thing is, how do you setup your website to use this php file to be able to handle all those HTTP Status Codes gracefully?  You just need to configure your server to use that php file for any Status Codes you want.  If you are building an ErrorDocument handling system for a server-wide, multi-site, setup, you will want to instead use the method I use.  Instead of using a separate language like PHP, Python, Ruby, Perl, etc, to handle errors, I rely on the very safe and fast SSI method.  I detailed the <a href="http://www.askapache.com/htaccess/advanced-htaccess-ssi.html">advanced ErrorDocument SSI</a> (<code>.htaccess</code> or <tt>httpd.conf</tt>)..</p>
<p>If you instead like most of us, you will be setting this up for 1 site, or 1 DOCUMENT_ROOT serving virtual hosts.  For that the best method is to modify your .htaccess file.</p>

<h3>Using Redirect in .htaccess to trigger Errors</h3>
<p>This is one of my all time favorite discoveries from my apache studies.  It's documented <a href="http://www.askapache.com/htaccess/apache-status-code-headers-errordocument.html">elsewhere</a> on this site, but if you want to test it out, just request <code>www.askapache.com/show-error-402</code>.  Of course the error handling that I have in place is quite nice.  </p>
<pre>Redirect 400 /show-error-400
Redirect 401 /show-error-401
Redirect 402 /show-error-402
Redirect 403 /show-error-403
Redirect 405 /show-error-405
Redirect 406 /show-error-406
Redirect 407 /show-error-407
Redirect 408 /show-error-408
Redirect 409 /show-error-409
Redirect 410 /show-error-410
Redirect 411 /show-error-411
Redirect 412 /show-error-412
Redirect 413 /show-error-413
Redirect 414 /show-error-414
Redirect 415 /show-error-415
Redirect 416 /show-error-416
Redirect 417 /show-error-417
Redirect 418 /show-error-418
Redirect 419 /show-error-419
Redirect 420 /show-error-420
Redirect 421 /show-error-421
Redirect 422 /show-error-422
Redirect 423 /show-error-423
Redirect 424 /show-error-424
Redirect 425 /show-error-425
Redirect 426 /show-error-426
Redirect 500 /show-error-500
Redirect 501 /show-error-501
Redirect 502 /show-error-502
Redirect 503 /show-error-503
Redirect 504 /show-error-504
Redirect 505 /show-error-505
Redirect 506 /show-error-506
Redirect 507 /show-error-507
Redirect 508 /show-error-508
Redirect 509 /show-error-509
Redirect 510 /show-error-510</pre>


<h3>Powerful Mod_Rewrite Trick</h3>
<p>Here's how to combine the power of mod_rewrites ability to parse requests and environment variables with the above Redirect trick to trigger a specific ErrorDocument based on the query_string parameter error.  This trick is only on AskApache.com, very powerful trick if you need to force ErrorDocuments.</p>
<pre>RewriteCond %{QUERY_STRING} error=([4|5][0-9][0-9]) [NC]
RewriteCond %{QUERY_STRING} !404
RewriteRule . /show-error-%1 [L]</pre>



<h2>ErrorDocument Example for .htaccess</h2>
<p>So if you save the php file as <code>err.php</code> in your DOCUMENT_ROOT, these are the htaccess commands that will enable its use.</p>
<p>The addition of the <code>?error=num</code> should be unneccessary on a good linux machine, it's a way for lesser OS's and webhosts to still be able to use errordocuments.  Basically Apache handles ErrorDocuments by setting special DEBUGGING variables (Start with <code>REDIRECT_</code>) so it's very easy to determine the STATUS CODE by just viewing <code>$_SERVER[&#039;REDIRECT_STATUS&#039;]</code>.  If a recursive type of redirect is going on, you may see <code>$_SERVER[&#039;REDIRECT_REDIRECT_STATUS&#039;]</code>.  Dumb (consistently) OS's like a Windows server almost always have problems with things like that, because they don't give a hoot about POSIX or standards, why should they when no one can view their code anyway.  <a href="http://www.askapache.com/htaccess/php-cgi-redirect_status.html">Here</a> are some more details on the <code>REDIRECT_STATUS</code> and other ways to use these variables.</p>
<p>If you want to learn how to enumerate and view the different variables that are in your Apache environment, I think I have the best tutorial on the planet for how to do this with <a href="http://www.askapache.com/htaccess/crazy-advanced-mod_rewrite-tutorial.html">PHP and mod_rewrite with mod_headers</a>.  That article is the basis for anyone who is hired to do mod_rewrites on a new server without root access.  I would say that one article will inform you more about mod_rewrite then any other article on this site.</p>
<pre>###
# ErrorDocument: In the event of a problem or error, what the server will return to the client. URLs
# can begin with a / for local web-paths (relative to DocumentRoot), or be a full URL which the client
# can resolve. Alternatively, a message can be displayed.  If a malformed request is detected, normal
# request processing will be immediately halted and the internal error message returned.
#
# Prior to version 2.0, messages were indicated by prefixing them with a
# single unmatched double quote character.
#
# The special value default can be used to specify Apache&#039;s simple hardcoded message and
# will restore Apache&#039;s simple hardcoded message.
#
ErrorDocument 400 /err.php?error=400
ErrorDocument 401 /err.php?error=401
ErrorDocument 402 /err.php?error=402
ErrorDocument 403 /err.php?error=403
ErrorDocument 404 /err.php?error=404
ErrorDocument 405 /err.php?error=405
ErrorDocument 406 /err.php?error=406
ErrorDocument 407 /err.php?error=407
ErrorDocument 408 /err.php?error=408
ErrorDocument 409 /err.php?error=409
ErrorDocument 410 /err.php?error=410
ErrorDocument 411 /err.php?error=411
ErrorDocument 412 /err.php?error=412
ErrorDocument 413 /err.php?error=413
ErrorDocument 414 /err.php?error=414
ErrorDocument 415 /err.php?error=415
ErrorDocument 416 /err.php?error=416
ErrorDocument 417 /err.php?error=417
ErrorDocument 422 /err.php?error=422
ErrorDocument 423 /err.php?error=423
ErrorDocument 424 /err.php?error=424
ErrorDocument 426 /err.php?error=426
ErrorDocument 500 /err.php?error=500
ErrorDocument 501 /err.php?error=501
ErrorDocument 502 /err.php?error=502
ErrorDocument 503 /err.php?error=503
ErrorDocument 504 /err.php?error=504
ErrorDocument 505 /err.php?error=505
ErrorDocument 506 /err.php?error=506
ErrorDocument 507 /err.php?error=507
ErrorDocument 510 /err.php?error=510</pre><p><a href="http://www.askapache.com/php/php-errordocument.html"></a><a href="http://www.askapache.com/php/php-errordocument.html">PHP to handle HTTP Status Codes for ErrorDocument</a> originally appeared on <cite>AskApache.com</cite> </p>]]></content:encoded>
			<wfw:commentRss>http://www.askapache.com/php/php-errordocument.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Mod_Rewrite Variables Cheatsheet</title>
		<link>http://www.askapache.com/htaccess/mod_rewrite-variables-cheatsheet.html</link>
		<comments>http://www.askapache.com/htaccess/mod_rewrite-variables-cheatsheet.html#comments</comments>
		<pubDate>Tue, 03 Aug 2010 15:05:23 +0000</pubDate>
		<dc:creator>AskApache</dc:creator>
				<category><![CDATA[Htaccess]]></category>

		<guid isPermaLink="false">http://www.askapache.com/?p=1280</guid>
		<description><![CDATA[<p><a class="IFL hs hs21" href="http://www.askapache.com/htaccess/mod_rewrite-variables-cheatsheet.html" title="mod_rewrite cheatsheet for .htaccess rewrites"></a>We've figured out what <a href="http://www.askapache.com/htaccess/crazy-advanced-mod_rewrite-tutorial.html">mod_rewrite variables</a> look like, a cheatsheet of the actual value. <br class="C" /></p>]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.askapache.com/htaccess/mod_rewrite-variables-cheatsheet.html"></a><a href="http://www.askapache.com/htaccess/mod_rewrite-variables-cheatsheet.html"><cite>AskApache.com</cite></a></p><p><a class="IFL hs hs21" href="http://uploads.askapache.com/2008/09/warningiconimg.jpg" title="mod_rewrite cheatsheet for .htaccess rewrites"></a>We've figured out what <a href="http://www.askapache.com/htaccess/crazy-advanced-mod_rewrite-tutorial.html">mod_rewrite variables</a> look like so we can create rewriterules and condition patterns based on the actual value.  This cheatsheet is where we'll lay them all out for quick reference.  This cheatsheet changed my life, way more than 301 redirect htaccess.<br class="C" /></p>

<h2>mod_rewrite Variable Value Cheat-Sheet</h2>
<p>Jump to: <a href="#API_VERSION">API_VERSION</a>, <a href="#AUTH_TYPE">AUTH_TYPE</a>, <a href="#CONTENT_LENGTH">CONTENT_LENGTH</a>, <a href="#CONTENT_TYPE">CONTENT_TYPE</a>, <a href="#DOCUMENT_ROOT">DOCUMENT_ROOT</a>, <a href="#GATEWAY_INTERFACE">GATEWAY_INTERFACE</a>, <a href="#HTTPS">HTTPS</a>, <a href="#HTTP_ACCEPT">HTTP_ACCEPT</a>, <a href="#HTTP_ACCEPT_CHARSET">HTTP_ACCEPT_CHARSET</a>, <a href="#HTTP_ACCEPT_ENCODING">HTTP_ACCEPT_ENCODING</a>, <a href="#HTTP_ACCEPT_LANGUAGE">HTTP_ACCEPT_LANGUAGE</a>, <a href="#HTTP_CACHE_CONTROL">HTTP_CACHE_CONTROL</a>, <a href="#HTTP_CONNECTION">HTTP_CONNECTION</a>, <a href="#HTTP_COOKIE">HTTP_COOKIE</a>, <a href="#HTTP_FORWARDED">HTTP_FORWARDED</a>, <a href="#HTTP_HOST">HTTP_HOST</a>, <a href="#HTTP_KEEP_ALIVE">HTTP_KEEP_ALIVE</a>, <a href="#HTTP_PROXY_CONNECTION">HTTP_PROXY_CONNECTION</a>, <a href="#HTTP_REFERER">HTTP_REFERER</a>, <a href="#HTTP_USER_AGENT">HTTP_USER_AGENT</a>, <a href="#IS_SUBREQ">IS_SUBREQ</a>, <a href="#ORIG_PATH_INFO">ORIG_PATH_INFO</a>, <a href="#ORIG_PATH_TRANSLATED">ORIG_PATH_TRANSLATED</a>, <a href="#ORIG_SCRIPT_FILENAME">ORIG_SCRIPT_FILENAME</a>, <a href="#ORIG_SCRIPT_NAME">ORIG_SCRIPT_NAME</a>, <a href="#PATH">PATH</a>, <a href="#PATH_INFO">PATH_INFO</a>, <a href="#PHP_SELF">PHP_SELF</a>, <a href="#QUERY_STRING">QUERY_STRING</a>, <a href="#REDIRECT_QUERY_STRING">REDIRECT_QUERY_STRING</a>, <a href="#REDIRECT_REMOTE_USER">REDIRECT_REMOTE_USER</a>, <a href="#REDIRECT_STATUS">REDIRECT_STATUS</a>, <a href="#REDIRECT_URL">REDIRECT_URL</a>, <a href="#REMOTE_ADDR">REMOTE_ADDR</a>, <a href="#REMOTE_HOST">REMOTE_HOST</a>, <a href="#REMOTE_IDENT">REMOTE_IDENT</a>, <a href="#REMOTE_PORT">REMOTE_PORT</a>, <a href="#REMOTE_USER">REMOTE_USER</a>, <a href="#REQUEST_FILENAME">REQUEST_FILENAME</a>, <a href="#REQUEST_METHOD">REQUEST_METHOD</a>, <a href="#REQUEST_TIME">REQUEST_TIME</a>, <a href="#REQUEST_URI">REQUEST_URI</a>, <a href="#SCRIPT_FILENAME">SCRIPT_FILENAME</a>, <a href="#SCRIPT_GROUP">SCRIPT_GROUP</a>, <a href="#SCRIPT_NAME">SCRIPT_NAME</a>, <a href="#SCRIPT_URI">SCRIPT_URI</a>, <a href="#SCRIPT_URL">SCRIPT_URL</a>, <a href="#SCRIPT_USER">SCRIPT_USER</a>, <a href="#SERVER_ADDR">SERVER_ADDR</a>, <a href="#SERVER_ADMIN">SERVER_ADMIN</a>, <a href="#SERVER_NAME">SERVER_NAME</a>, <a href="#SERVER_PORT">SERVER_PORT</a>, <a href="#SERVER_PROTOCOL">SERVER_PROTOCOL</a>, <a href="#SERVER_SIGNATURE">SERVER_SIGNATURE</a>, <a href="#SERVER_SOFTWARE">SERVER_SOFTWARE</a>, <a href="#THE_REQUEST">THE_REQUEST</a>, <a href="#TIME">TIME</a>, <a href="#TIME_DAY">TIME_DAY</a>, <a href="#TIME_HOUR">TIME_HOUR</a>, <a href="#TIME_MIN">TIME_MIN</a>, <a href="#TIME_MON">TIME_MON</a>, <a href="#TIME_SEC">TIME_SEC</a>, <a href="#TIME_WDAY">TIME_WDAY</a>, <a href="#TIME_YEAR">TIME_YEAR</a>, <a href="#TZ">TZ</a>, <a href="#UNIQUE_ID">UNIQUE_ID</a></p>
<dl class="dl1">
<dt><a id="API_VERSION"></a><br />API_VERSION</a>: <code>20020903:12</code></dt>
<dd><pre>RewriteCond %{API_VERSION} ^(.*)$
RewriteRule .* http://www.askapache.com?API_VERSION=%1 [R=307,L]</pre></dd>
<dt><a id="AUTH_TYPE"></a><br />AUTH_TYPE</a>: <code>Digest</code></dt>
<dd><pre>RewriteRule .* - [E=IN_AUTH_TYPE:%{AUTH_TYPE}]
RequestHeader set AUTH_TYPE "%{IN_AUTH_TYPE}e"</pre></dd>
<dt><a id="CACHE_CONTROL"></a><br />CACHE_CONTROL</a>: <code>max-age=0</code></dt>
<dd><pre>RewriteCond %{ENV:CACHE_CONTROL} no-cache [NC]
RewriteRule . %{REQUEST_URI}?nocache [L]</pre></dd>
<dt><a id="CONNECTION"></a><br />CONNECTION</a>: <code>keep-alive</code></dt>
<dd></dd>
<dt><a id="CONTENT_LENGTH"></a><br />CONTENT_LENGTH</a>: <code>(null)</code></dt>
<dd><pre>RewriteCond %{REQUEST_METHOD} =POST
RewriteCond %{HTTP:Content-Length}%{CONTENT_LENGTH} ^$
RewriteRule .* - [F,NS,L]</pre></dd>
<dt><a id="CONTENT_TYPE"></a><br />CONTENT_TYPE</a>: <code>(null)</code></dt>
<dd></dd>
<dt><a id="DOCUMENT_ROOT"></a><br />DOCUMENT_ROOT</a>: <code>/home/webroot/askapache.com</code></dt>
<dd><pre>RewriteCond %{DOCUMENT_ROOT}/cache%{REQUEST_URI}/index.html -f
RewriteRule . /cache%{REQUEST_URI}/index.html</pre></dd>
<dt><a id="HOST"></a><br />HOST</a>: <code>www.askapache.com</code></dt>
<dd><pre>RewriteCond %{HTTP_HOST} !^www\.askapache\.com$ [NC]
RewriteRule . http://www.askapache.com%{REQUEST_URI} [R=301,L]</pre></dd>
<dt><a id="HTTP"></a><br />HTTP</a>:</dt>
<dd><pre>RewriteCond %{HTTP:Accept-Encoding} gzip [NC]
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI}.gz -f
RewriteRule . %{REQUEST_URI}.gz [L]</pre></dd>
<dt><a id="HTTPS"></a><br />HTTPS</a>: <code>off</code></dt>
<dd><pre>RewriteCond %{HTTPS} !=on
RewriteRule .* https://%{SERVER_NAME}%{REQUEST_URI} [R=301,L]</pre></dd>
<dt><a id="HTTP_ACCEPT"></a><br />HTTP_ACCEPT</a>: <code>text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8</code></dt>
<dd></dd>
<dt><a id="HTTP_COOKIE"></a><br />HTTP_COOKIE</a>: <code>__qca=1176541205adf28-5553185; ASKAPACHEID=fdadfa4f33e62a878468; __utmc=1df3893</code></dt>
<dd><pre>RewriteCond %{HTTP_COOKIE} ^.*autostart=on.*$
RewriteRule ^(.*)\.swf$ /$1\?autostart=true [NE,L]</pre></dd>
<dt><a id="HTTP_HOST"></a><br />HTTP_HOST</a>: <code>www.askapache.com</code></dt>
<dd></dd>
<dt><a id="HTTP_REFERER"></a><br />HTTP_REFERER</a>: <code>http://www.askapache.com/pro/mod_rewrite/catch.php?k=i</code></dt>
<dd><pre>RewriteCond %{HTTP_REFERER} badhost [NC]
RewriteRule . - [F]</pre></dd>
<dt><a id="HTTP_USER_AGENT"></a><br />HTTP_USER_AGENT</a>: <code>Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9) Firefox/3.0.1</code></dt>
<dd><pre>RewriteCond %{HTTP_USER_AGENT} ^.*(Android|2.0\ MMP|240x320|AvantGo|BlackBerry|Blazer|Cellphone|Danger|DoCoMo|Elaine/3.0|EudoraWeb|hiptop|IEMobile|iPhone).*$ [NC]
RewriteRule ^(.+)$ /mobile/$1 [L]</pre></dd>
<dt><a id="IS_SUBREQ"></a><br />IS_SUBREQ</a>: <code>false</code></dt>
<dd></dd>
<dt><a id="KEEP_ALIVE"></a><br />KEEP_ALIVE</a>: <code>300</code></dt>
<dd></dd>
<dt><a id="PATH"></a><br />PATH</a>: <code>/bin:/usr/bin:/sbin:/usr/sbin</code></dt>
<dd></dd>
<dt><a id="QUERY_STRING"></a><br />QUERY_STRING</a>: <code>k=i</code></dt>
<dd><pre>RewriteCond %{QUERY_STRING} showtime [NC]
RewriteCond T:%{TIME}_TY:%{TIME_YEAR}_TMO:%{TIME_MON}_TWD:%{TIME_WDAY}_TD:%{TIME_DAY}_TH:%{TIME_HOUR}_TMI:%{TIME_MIN}_TS:%{TIME_SEC} ^(.*)$
RewriteRule .* http://%{HTTP_HOST}%{REQUEST_URI}?time=%1 [R,L]</pre></dd>
<dt><a id="REMOTE_ADDR"></a><br />REMOTE_ADDR</a>: <code>22.162.134.211</code></dt>
<dd><pre>RewriteCond %{REMOTE_ADDR} !^22\.162\.134\.211$
RewriteRule . http://www.askapache.com/maintenance-in-progress.html [R=307,L]</pre></dd>
<dt><a id="REMOTE_HOST"></a><br />REMOTE_HOST</a>: <code>22.162.134.211</code></dt>
<dd></dd>
<dt><a id="REMOTE_PORT"></a><br />REMOTE_PORT</a>: <code>4220</code></dt>
<dd></dd>
<dt><a id="REMOTE_USER"></a><br />REMOTE_USER</a>: <code>askapache</code></dt>
<dd><pre>RewriteRule .* - [E=REMOTE_USER:%{HTTP:Authorization}]</pre></dd>
<dt><a id="REQUEST_FILENAME"></a><br />REQUEST_FILENAME</a>: <code>/home/webroot/askapache.com/pro/mod_rewrite/index.php</code></dt>
<dd></dd>
<dt><a id="REQUEST_METHOD"></a><br />REQUEST_METHOD</a>: <code>GET</code></dt>
<dd><pre>RewriteCond %{REQUEST_METHOD} !^(POST|GET|HEAD|PROPFIND|OPTIONS)$
RewriteRule .* - [F,L]</pre></dd>
<dt><a id="REQUEST_PROTOCOL"></a><br />REQUEST_PROTOCOL</a>: <code>HTTP/1.1</code></dt>
<dd><pre>RewriteCond %{REQUEST_PROTOCOL} !^HTTP/(0\.9|1\.[01])$
RewriteRule . [F,L]</pre></dd>
<dt><a id="REQUEST_URI"></a><br />REQUEST_URI</a>: <code>/pro/mod_rewrite/index.php</code></dt>
<dd><pre>RewriteCond %{REQUEST_URI} ^(robots\.txt|favicon\|ico)$ [NC]
RewriteRule . - [S=1]
RewriteCond %{HTTP_HOST} ^www
RewriteRule .* http://%{SERVER_NAME}%{REQUEST_URI} [R=301,L]</pre></dd>
<dt><a id="SCRIPT_FILENAME"></a><br />SCRIPT_FILENAME</a>: <code>/home/webroot/askapache.com/pro/mod_rewrite/index.php</code></dt>
<dd></dd>
<dt><a id="SCRIPT_GROUP"></a><br />SCRIPT_GROUP</a>: <code>daemong</code></dt>
<dd></dd>
<dt><a id="SCRIPT_URI"></a><br />SCRIPT_URI</a>: <code>http://www.askapache.com/pro/mod_rewrite/index.php</code></dt>
<dd></dd>
<dt><a id="SCRIPT_URL"></a><br />SCRIPT_URL</a>: <code>/pro/mod_rewrite/index.php</code></dt>
<dd></dd>
<dt><a id="SCRIPT_USER"></a><br />SCRIPT_USER</a>: <code>askapache</code></dt>
<dd></dd>
<dt><a id="SERVER_ADDR"></a><br />SERVER_ADDR</a>: <code>208.113.134.190</code></dt>
<dd></dd>
<dt><a id="SERVER_ADMIN"></a><br />SERVER_ADMIN</a>: <code>webmaster@askapache.com</code></dt>
<dd></dd>
<dt><a id="SERVER_NAME"></a><br />SERVER_NAME</a>: <code>www.askapache.com</code></dt>
<dd></dd>
<dt><a id="SERVER_PORT"></a><br />SERVER_PORT</a>: <code>80</code></dt>
<dd></dd>
<dt><a id="SERVER_PROTOCOL"></a><br />SERVER_PROTOCOL</a>: <code>HTTP/1.1</code></dt>
<dd></dd>
<dt><a id="SERVER_SOFTWARE"></a><br />SERVER_SOFTWARE</a>: <code>Apache/2.0.61 (Unix) PHP/5.5 OpenSSL/0.9.7e</code></dt>
<dd></dd>
<dt><a id="THE_REQUEST"></a><br />THE_REQUEST</a>: <code>GET /pro/mod_rewrite/index.php?k=i HTTP/1.1</code></dt>
<dd><pre>RewriteCond %{THE_REQUEST} ^(GET|POST)\ /.*\?(s|search)=(.+)\ HTTP/ [NC]
RewriteRule .* http://www.askapache.com/search/%3/? [R=302,L,NE]</pre></dd>
<dt><a id="TIME"></a><br />TIME</a>: <code>20080915152142</code></dt>
<dd><pre>RewriteCond %{QUERY_STRING} showtime [NC]
RewriteCond T:%{TIME}_TY:%{TIME_YEAR}_TMO:%{TIME_MON}_TWD:%{TIME_WDAY}_TD:%{TIME_DAY}_TH:%{TIME_HOUR}_TMI:%{TIME_MIN}_TS:%{TIME_SEC} ^(.*)$
RewriteRule .* http://%{HTTP_HOST}%{REQUEST_URI}?time=%1 [R,L]</pre></dd>
<dt><a id="TIME_DAY"></a><br />TIME_DAY</a>: <code>15</code></dt>
<dd></dd>
<dt><a id="TIME_HOUR"></a><br />TIME_HOUR</a>: <code>15</code></dt>
<dd></dd>
<dt><a id="TIME_MIN"></a><br />TIME_MIN</a>: <code>21</code></dt>
<dd></dd>
<dt><a id="TIME_MON"></a><br />TIME_MON</a>: <code>09</code></dt>
<dd></dd>
<dt><a id="TIME_SEC"></a><br />TIME_SEC</a>: <code>42</code></dt>
<dd></dd>
<dt><a id="TIME_WDAY"></a><br />TIME_WDAY</a>: <code>1</code></dt>
<dd></dd>
<dt><a id="TIME_YEAR"></a><br />TIME_YEAR</a>: <code>2008</code></dt>
<dd></dd>
<dt><a id="UNIQUE_ID"></a><br />UNIQUE_ID</a>: <code>qOr5tEBvcm8AAE-VoiUAAAAQ</code></dt>
<dd></dd>
</dl>

<p>This article is meant to prepare us for the advanced mod_rewrite examples that are soon to be published.  The upcoming article is going to be examples using <a href="http://www.askapache.com/htaccess/mod_rewrite-tips-and-tricks.html">mod_rewrite</a> to achieve some crazy stuff...  Here the focus is on identifying mod_rewrite variables and defining the limits of the module by checking the <a href='http://www.askapache.com/servers/mod_rewrite.c.html'>mod_rewrite source code</a>.<br class="C" /></p>


<p class="cnote">For a broader mod_rewrite cheat sheet, check this <a href="http://www.addedbytes.com/apache/mod_rewrite-cheat-sheet/">printable</a> cheat sheet.</p>


<h2>Directives in Mod_Rewrite</h2>
<dl>
<dt>RewriteEngine</dt>
<dd><pre>RewriteEngine on|off</pre> On or Off to enable or disable (default) the whole rewriting engine</dd>
<dt>RewriteOptions</dt>
<dd><pre>RewriteOptions Options</pre> List of option strings to set</dd>

<dt>RewriteBase</dt>
<dd><pre>RewriteBase URL-path</pre> the base URL of the per-directory context
<dt>RewriteCond</dt>
<dd><pre>RewriteCond TestString CondPattern</pre> an input string and a to be applied regexp-pattern
<dt>RewriteRule</dt>
<dd><pre>RewriteRule Pattern Substitution [flags]</pre> an URL-applied regexp-pattern and a substitution URL
<dt>RewriteMap</dt>
<dd><pre>RewriteMap MapName MapType:MapSource</pre> a mapname and a filename
<dt>RewriteLock</dt>
<dd><pre>RewriteLock file-path</pre> the filename of a lockfile used for inter-process synchronization
<dt>RewriteLog</dt>
<dd><pre>RewriteLog file-path</pre> the filename of the rewriting logfile
<dt>RewriteLogLevel</dt>
<dd><pre>RewriteLogLevel Level</pre> the level of the rewriting logfile verbosity (0=none, 1=std, .., 9=max)
</dl>



<h2>RewriteRule Flags</h2>
<dl>
<dt><abbr title="Chain">C</abbr></dt>
<dd>Using the [Chain], or [C] flag, allows you to indicate that several rules should be chained together as a single logical transation. This is usually used when a transformation is sufficiently complicated to warrant breaking into several smaller steps.</dd>
<dt><abbr title="CO - Cookie</dt>
<dd><pre>cookie|CO=Name:Value:Domain[:Lifetime[:Path]]</pre><br />
This sets a cookie on the client's browser. The cookie's name is specified by NAME and the value is VAL. The domain field is the domain of the cookie, such as '.apache.org',the optional lifetime is the lifetime of the cookie in minutes, and the optional path is the path of the cookie.</dd>
<dt><abbr title="Env">E</abbr></dt>
<dd><pre>&#039;env|E=VAR:VAL&#039; (set environment variable)</pre><br />
RewriteRule (root|cmd)\.exe - [E=worm:nimda]
</dd>
<dt><abbr title="Forbidden">F</abbr></dt>
<dd><pre>&#039;forbidden|F&#039; (force URL to be forbidden)</pre><br />
</dd>
<dt><abbr title="Gone">G</abbr></dt>
<dd><pre>&#039;gone|G&#039; (force URL to be gone)</pre><br />
</dd>
<dt><abbr title="Handler">H</abbr></dt>
<dd><pre>&#039;handler|H=Content-handler&#039; (force Content handler)</pre><br />
</dd>
<dt><abbr title="Last">L</abbr></dt>
<dd><pre>&#039;last|L&#039; (last rule)</pre><br />
</dd>
<dt><abbr title="Next">N</abbr></dt>
<dd><pre>&#039;next|N&#039; (next round)</pre><br />
</dd>
<dt><abbr title="No Case">NC</abbr></dt>
<dd><pre>&#039;nocase|NC&#039; (no case)</pre><br />
</dd>
<dt><abbr title="No Escape">NE</abbr></dt>
<dd><pre>&#039;noescape|NE&#039; (no URI escaping of output)</pre><br />
</dd>
<dt><abbr title="No Subrequest">NS</abbr></dt>
<dd><pre>&#039;nosubreq|NS&#039; (not for internal sub-requests)</pre><br />
</dd>
<dt><abbr title="Proxy">P</abbr></dt>
<dd><pre>&#039;proxy|P&#039; (force proxy)</pre><br />
</dd>
<dt><abbr title="pass through">PT</abbr></dt>
<dd><pre>&#039;passthrough|PT&#039; (pass through to next handler)</pre><br />
</dd>
<dt><abbr title="Query String Append">QSA</abbr></dt>
<dd><pre>&#039;qsappend|QSA&#039; (query string append)</pre><br />
</dd>
<dt><abbr title="Redirect">R</abbr></dt>
<dd><pre>&#039;redirect|R  [=code]&#039; (force redirect)</pre><br />
</dd>
<dt><abbr title="Skip">S</abbr></dt>
<dd><pre>&#039;skip|S=num&#039; (skip next rule(s))</pre><br />

This flag forces the rewriting engine to skip the next num rules in sequence, if the current rule matches. Use this to make pseudo if-then-else constructs: The last rule of the then-clause becomes skip=N, where N is the number of rules in the else-clause. (This is not the same as the 'chain|C' flag!)</dd>
<dt><abbr title="Type">T</abbr></dt>
<dd><pre>&#039;type|T=MIME-type&#039; (force MIME type)</pre><br />
Force the MIME-type of the target file to be MIME-type. This can be used to set up the content-type based on some conditions. For example, the following snippet allows .php files to be displayed by mod_php if they are called with the .phps extension:
</dd>
</dl>


<h2>Rules and Conditions Processing Order</h2>
<ol>
<li>The Pattern of the RewriteRule (^/.*$) is checked first.</li>
<li>If the pattern matches, then the RewriteCond's are checked.</li>
<li>If the RewriteConditions also match, the RewriteRule is applied.</li>
</ol>



<h2>RewriteRule Special Variables</h2>
<ol>
<li><strong>ENV_</strong></li>
<li><strong>SSL_</strong></li>
<li><strong>HTTP_</strong></li>
<li><strong>LA-U_</strong></li>
<li><strong>LA-F_</strong></li>
</ol>


<h2>RewriteCond Tests</h2>
<ul>
<li><strong>f</strong> - FILE_EXISTS</li>
<li><strong>s</strong> - FILE_SIZE</li>
<li><strong>l</strong> - FILE_LINK</li>
<li><strong>d</strong> - FILE_DIR</li>
<li><strong>x</strong> - FILE_XBIT</li>
<li><strong>U</strong> - LU_URL</li>
<li><strong>F</strong> - LU_FILE</li>
<li><strong>&gt;</strong> - STR_GT</li>
<li><strong>&lt;</strong> - STR_LT</li>
<li><strong>=</strong> - STR_EQ</li>
</ul>



<h2>Special Rewrite Redirects</h2>
<ol>
<li>"permanent" - HTTP_MOVED_PERMANENTLY</li>
<li>"temp" - HTTP_MOVED_TEMPORARILY</li>
<li>"seeother" - HTTP_SEE_OTHER</li>
<li>digit</li>
</ol>


<h2>Recognized by Mod_Rewrite</h2>
<ol>
<li>ajp://</li>
<li>balancer://</li>
<li>ftp://</li>
<li>gopher://</li>
<li>http://</li>
<li>https://</li>
<li>ldap://</li>
<li>mailto:</li>
<li>news:</li>
<li>nntp://</li>
</ol>



<h2>Mod_Rewrite Variables, from Source</h2>
<ul>
<li>TIME - <code>%04d%02d%02d%02d%02d%02d</code></li>
<li>HTTPS - <code>flag ? "on" : "off"</code></li>
<li>TIME_DAY</li>
<li>TIME_SEC</li>
<li>TIME_MIN</li>
<li>TIME_HOUR</li>
<li>TIME_MON</li>
<li>TIME_WDAY</li>
<li>TIME_YEAR</li>
<li>IS_SUBREQ - <code> (main ? "true" : "false");</code></li>
<li>PATH_INFO - <code> path_info;</code></li>
<li>AUTH_TYPE - <code> ap_auth_type;</code></li>
<li>HTTP_HOST - <code> lookup_header("Host", ctx);</code></li>
<li>SERVER_NAME - <code> ap_get_server_name(r);</code></li>
<li>REMOTE_ADDR - <code> connection-&gt;remote_ip;</code></li>
<li>SERVER_ADDR - <code> connection-&gt;local_ip;</code></li>
<li>HTTP_ACCEPT - <code> lookup_header("Accept", ctx);</code></li>
<li>THE_REQUEST - <code> the_request;</code></li>
<li>API_VERSION - <code> "%d:%d",MODULE_MAGIC_NUMBER_MAJOR,MODULE_MAGIC_NUMBER_MINOR);</code></li>
<li>HTTP_COOKIE - <code> lookup_header("Cookie", ctx);</code></li>
<li>SERVER_PORT - <code> ap_get_server_port(r);</code></li>
<li>REMOTE_HOST</li>
<li>REMOTE_NAME, NULL);</code></li>
<li>REMOTE_PORT - <code> r-&gt;connection-&gt;remote_addr-&gt;port</code></li>
<li>REMOTE_USER - <code> user;</code></li>
<li>SCRIPT_USER - <code> "&lt;unknown&gt;";</code></li>
<li>APR_FINFO_USER</li>
<li>REQUEST_URI - <code> uri;</code></li>
<li>SCRIPT_GROUP - <code> "&lt;unknown&gt;";</code></li>
<li>REMOTE_IDENT - <code> ap_get_remote_logname(r);</code></li>
<li>HTTP_REFERER - <code> lookup_header("Referer", ctx);</code></li>
<li>QUERY_STRING - <code> args;</code></li>
<li>SERVER_ADMIN - <code> server-&gt;server_admin;</code></li>
<li>DOCUMENT_ROOT - <code> ap_document_root(r);</code></li>
<li>HTTP_FORWARDED - <code>lookup_header("Forwarded", ctx);</code></li>
<li>REQUEST_METHOD - <code>method;</code></li>
<li>HTTP_USER_AGENT - <code>lookup_header("User-Agent", ctx);</code></li>
<li>SCRIPT_FILENAME - <code> same as request_filename </code></li>
<li>REQUEST_FILENAME - <code> same as script_filename </code></li>
<li>SERVER_PROTOCOL - <code>protocol</code></li>
<li>SERVER_SOFTWARE - <code>ap_get_server_banner();</code></li>
<li>HTTP_PROXY_CONNECTION - <code>lookup_header("Proxy-Connection", ctx);</code></li>
</ul>


<h2>REGEX Rewrite Guides</h2>
<ul>
<li><a href="http://www.rankinglabs.com/Mod_Rewrite">Mod_Rewrite: Flags, Rules, Conditions, Tutorial and Variables</a></li>
<li><a href="http://etext.lib.virginia.edu/services/helpsheets/unix/regex.html" title="Stephen Ramsay - Electronic Text Center - University of Virginia ">Using Regular Expressions</a></li>
<li><a href="http://check-these.info/mod_rewrite-basic.html">RewriteRule (mod_rewrite) guide</a></li>
</ul>


<h2>Mod_Rewrite Terms and Definitions</h2>
<dl>
<dt>pattern</dt><dd>the RegExp pattern string</dd>
<dt>regexp<dt><dd>the RegExp pattern compilation</dd>
<dt>flags</dt>
<dd>Flags which control the substitution</dd>
<dt>forced_mimetype</dt>
<dd>forced MIME type of substitution</dd>
<dt>forced_handler</dt>
<dd>forced content handler of subst.</dd>
<dt>forced_responsecode</dt>
<dd>forced HTTP response status</dd>
<dt>env</dt>
<dd>added environment variables</dd>
<dt>cookie</dt>
<dd>added cookies</dd>
<dt>skip</dt>
<dd>number of next rules to skip</dd>
<dt>state</dt>
<dd>the RewriteEngine state</dd>
<dt>options</dt>
<dd>the RewriteOption state</dd>
<dt>rewritelogfile</dt>
<dd>the RewriteLog filename</dd>
<dt>rewritelogfp</dt>
<dd>the RewriteLog open filepointer</dd>
<dt>rewritelog:  level</dt>
<dd>the RewriteLog level of verbosity</dd>
<dt>rewritemaps</dt>
<dd>the RewriteMap entries</dd>
<dt>rewriteconds</dt>
<dd>the RewriteCond entries (temp.)</dd>
<dt>rewriterules</dt>
<dd>the RewriteRule entries</dd>
<dt>directory</dt>
<dd>the directory where it applies</dd>
<dt>baseurl</dt>
<dd>the base-URL  where it applies</dd>
</dl>


<h2>Mod_Rewrite Errors</h2>
<ul style="font-size:10px;">
<li><code>Options FollowSymLinks or SymLinksIfOwnerMatch is off  which implies that RewriteRule directive is forbidden:  %s</code></li>
<li><code>RewriteCond: bad argument line </code></li>
<li><code>RewriteCond: NoCase option for non-regex pattern %s  is not supported and will be ignored.</code></li>
<li><code>RewriteCond: cannot compile regular  expression </code></li>
<li><code>RewriteRule: invalid HTTP  response code %s for  flag R</code></li>
<li><code>RewriteRule: unknown flag </code></li>
<li><code>RewriteRule: cannot compile regular expression </code></li>
<li><code>RewriteOptions: MaxRedirects option has been  removed in favor of the global  LimitInternalRecursion directive and will be  ignored.</code></li>
<li><code>RewriteOptions: unknown option </code></li>
<li><code>RewriteMap: bad path to txt map: </code></li>
<li><code>RewriteMap: bad path to rnd map: </code></li>
<li><code>RewriteMap: bad map:</code></li>
<li><code>RewriteMap: bad path to dbm map: </code></li>
<li><code>RewriteMap: dbm type </code></li>
<li><code>RewriteMap: bad path to prg map: </code></li>
<li><code>RewriteMap: internal map not found:</code></li>
<li><code>RewriteMap: bad path to txt map: </code></li>
<li><code>RewriteMap: file for map not found:</code></li>
<li><code>Invalid RewriteLock path</code></li>
<li><code>RewriteBase: only valid in per-directory config files</code></li>
<li><code>RewriteBase: empty URL not allowed</code></li>
<li><code>RewriteBase: argument is not a valid URL</code></li>
<li><code>RewriteCond: bad flag delimiters</code></li>
<li><code>RewriteCond: unknown flag</code></li>
<li><code>RewriteLog and RewriteLogLevel are not supported by this build of mod_rewrite because it was compiled using the -DREWRITELOG_DISABLED compiler option. You have to recompile mod_rewrite WITHOUT this option in order to use the rewrite log.</code></li>
<li><code>mod_rewrite: Invalid RewriteLog  path %s</code></li>
<li><code>mod_rewrite: could not open reliable pipe  to RewriteLog filter %s</code></li>
<li><code>mod_rewrite: Invalid RewriteLog  path %s</code></li>
<li><code>mod_rewrite: could not open RewriteLog  file %s</code></li>
<li><code>mod_rewrite: Running external rewrite maps  without defining a RewriteLock is DANGEROUS!</code></li>
<li><code>mod_rewrite: could not start RewriteMap  program %s</code></li>
<li><code>mod_rewrite: cant access text RewriteMap file %s</code></li>
<li><code>mod_rewrite: cant access DBM RewriteMap file %s</code></li>
<li><code>mod_rewrite: Parent could not create RewriteLock  file %s</code></li>
<li><code>mod_rewrite: Parent could not set permissions  on RewriteLock check User and Group directives</code></li>
<li><code>mod_rewrite: could not create rewrite_log_lock</code></li>
<li><code>mod_rewrite: Could not set permissions on  rewrite_log_lock check User and Group directives</code></li>
<li><code>mod_rewrite: could not init rewrite_mapr_lock_acquire  in child</code></li>
<li><code>mod_rewrite: could not init rewrite log lock in child</code></li>
<li><code>mod_rewrite: could not init map cache in child</code></li>
<li><code>split uri=%s -&gt; uri=%s, args=%s</code></li>
<li><code>reduce %s -&gt; %s</code></li>
<li><code>strip matching prefix: %s -&gt; %s</code></li>
<li><code>add subst prefix: %s -&gt; %s</code></li>
<li><code>cant open RewriteMap file, see error log</code></li>
<li><code>cache lookup FAILED, forcing new map lookup</code></li>
<li><code>map lookup FAILED: map=%s[txt] key=%s</code></li>
<li><code>map lookup OK: map=%s[txt] key=%s -&gt; val=%s</code></li>
<li><code>cache lookup OK: map=%s[txt] key=%s -&gt; val=%s</code></li>
<li><code>randomly chosen the subvalue `%s</code></li>
<li><code>cant open DBM RewriteMap file, see error log</code></li>
<li><code>cache lookup FAILED, forcing new map lookup</code></li>
<li><code>map lookup FAILED: map=%s[dbm] key=%s</code></li>
<li><code>map lookup OK: map=%s[dbm] key=%s -&gt;  val=%s</code></li>
<li><code>cache lookup OK: map=%s[dbm] key=%s -&gt; val=%s</code></li>
<li><code>map lookup FAILED: map=%s key=%s</code></li>
<li><code>map lookup OK: map=%s key=%s -&gt; val=%s</code></li>
<li><code>map lookup FAILED: map=%s key=%s</code></li>
<li><code>map lookup OK: map=%s key=%s -&gt; val=%s</code></li>
<li><code>lookahead: path=%s var=%s  -&gt; val=%s</code></li>
<li><code>lookahead: path=%s var=%s  -&gt; val=%s</code></li>
<li><code>RESULT=%s</code></li>
<li><code>escaping backreference %s to %s</code></li>
<li><code>setting env variable %s to %s</code></li>
<li><code>setting cookie %s, cookie</code></li>
<li><code>skipping already set cookie %s</code></li>
<li><code>RewriteCond URI (-U) check:  path=%s -&gt; status=%d</code></li>
<li><code>RewriteCond file (-F) check: path=%s  -&gt; file=%s status=%d</code></li>
<li><code>RewriteCond: input=%s pattern=%s%s%s%s  =&gt; %s</code></li>
<li><code>remember %s to have MIME-type  %s</code></li>
<li><code>remember %s to have  Content-handler %s</code></li>
<li><code>add path info postfix: %s -&gt; %s%s</code></li>
<li><code>strip per-dir prefix: %s -&gt; %s</code></li>
<li><code>applying pattern %s to uri %s</code></li>
<li><code>rewrite %s -&gt; %s, ctx-&gt;uri</code></li>
<li><code>forcing responsecode %d for %s</code></li>
<li><code>add per-dir prefix: %s -&gt; %s%s</code></li>
<li><code>forcing proxy-throughput with %s</code></li>
<li><code>explicitly forcing redirect with %s</code></li>
<li><code>implicitly forcing redirect (rc=%d)  with %s</code></li>
<li><code>forcing %s to get passed through  to next API URI-to-filename handler</code></li>
<li><code>init rewrite engine with requested uri %s</code></li>
<li><code>go-ahead with proxy request  %s [OK]</code></li>
<li><code>dconf-&gt;directory,trying to replace prefix %s with %s</code></li>
<li><code>escaping %s for redirect</code></li>
<li><code>redirect to %s [REDIRECT/%d]</code></li>
<li><code>initial URL equal rewritten  URL: %s [IGNORING REWRITE]</code></li>
<li><code>dconf-&gt;directory, trying to replace prefix  %s with %s</code></li>
<li><code>strip document_root  prefix: %s -&gt; %s</code></li>
<li><code>internal redirect with %s  [INTERNAL REDIRECT]</code></li>
<li><code>pass through %s</code></li>
<li><code>force filename %s to have MIME-type %s</code></li>
<li><code>force filename %s to have the  Content-handler %s,</code></li>
<li><code>init rewrite engine with requested uri %s</code></li>
<li><code>init rewrite engine with passed filename  %s. Original uri = %s</code></li>
<li><code>uri already rewritten. Status %s, Uri %s,   %s</code></li>
<li><code>attempt to make remote request from mod_rewrite  without proxy enabled: %s</code></li>
<li><code>go-ahead with proxy request %s [OK]</code></li>
<li><code>escaping %s for redirect</code></li>
<li><code>redirect to %s [REDIRECT/%d]</code></li>
<li><code>local path result: %s</code></li>
<li><code>prefixing with document_root of %s  FAILED</code></li>
<li><code>prefixed with document_root to %s</code></li>
<li><code>go-ahead with %s [OK]</code></li>
<li><code>pass through %s</code></li>
</ul>



<h2>URL Rewriting Module</h2>
<blockquote cite="http://apache.askapache.com/httpd/httpd-2.2.8/modules/mappers/mod_rewrite.c">
<p>This module uses a rule-based rewriting engine (based on a regular-expression parser) to rewrite requested URLs on the fly.</p>
<p>It supports an unlimited number of additional rule conditions (which can operate on a lot of variables, even on HTTP headers) for granular matching and even external database lookups (either via plain text tables, DBM hash files or even external processes) for advanced URL substitution.</p>
<p>It operates on the full URLs (including the PATH_INFO part) both in per-server context (httpd.conf) and per-dir context (.htaccess) and even  can generate QUERY_STRING parts on result.  The rewriting result finally can lead to internal subprocessing, external request redirection or even to internal proxy throughput.</p>
<p>This module was originally written in April 1996 and gifted exclusively to the The Apache Software Foundation in July 1997 by</p>
<address class="vcard">
<a class="fn url" href="http://engelschall.com/" title="Ralf S. Engelschall">Ralf S. Engelschall</a>
<a class="fn email" href="http://engelschall.com/contact.php">rse [at] engenschall.com</a>
</address>
</blockquote><p><a href="http://www.askapache.com/htaccess/mod_rewrite-variables-cheatsheet.html"></a><a href="http://www.askapache.com/htaccess/mod_rewrite-variables-cheatsheet.html">Mod_Rewrite Variables Cheatsheet</a> originally appeared on <cite>AskApache.com</cite> </p>]]></content:encoded>
			<wfw:commentRss>http://www.askapache.com/htaccess/mod_rewrite-variables-cheatsheet.html/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
	</channel>
</rss>

