views:

1473

answers:

2

How can you use ModRewrite to check if a cache file exists, and if it does, rewrite to the cache file and otherwise rewrite to a dynamic file.

For example I have the following folder structure:

pages.php
cache/
  pages/
   1.html
   2.html
   textToo.html
   etc.

How would you setup the RewriteRules for this so request can be send like this:

example.com/pages/1

And if the cache file exists rewrite tot the cache file, and if the cache file does not exists, rewrite to pages.php?p=1

It should be something like this: (note that this does not work, otherwise I would not have asked this)

RewriteRule ^pages/([^/\.]+) cache/pages/$1.html [NC,QSA]
RewriteCond %{REQUEST_FILENAME} -f [NC,OR] 
RewriteCond %{REQUEST_FILENAME} -d [NC] 
RewriteRule cache/pages/([^/\.]+).html pages.php?p=$1 [NC,QSA,L]

I can off coarse do this using PHP but I thought it had to be possible using mod_rewrite.

+3  A: 
RewriteRule ^pages/([^/\.]+) cache/pages/$1.html [NC,QSA]

# At this point, we would have already re-written pages/4 to cache/pages/4.html
RewriteCond %{REQUEST_FILENAME} !-f

# If the above RewriteCond succeeded, we don't have a cache, so rewrite to 
# the pages.php URI, otherwise we fall off the end and go with the
# cache/pages/4.html
RewriteRule ^cache/pages/([^/\.]+).html pages.php?p=$1 [NC,QSA,L]

Turning off MultiViews is crucial (if you have them enabled) as well.

Options -MultiViews

Otherwise the initial request (/pages/...) will get automatically converted to /pages.php before mod_rewrite kicks in. You can also just rename pages.php to something else (and update the last rewrite rule as well) to avoid the MultiViews conflict.

Edit: I initially included RewriteCond ... !-d but it is extraneous.

Sean Bright
A: 

Another approach would be to first look if there is a chached representation available:

RewriteCond %{DOCUMENT_ROOT}/cache/$0 -f
RewriteRule ^pages/[^/\.]+$ cache/$0.html [L,QSA]

RewriteRule ^pages/([^/\.]+)$ pages.php?p=$1 [L,QSA]
Gumbo