Search code examples
apache.htaccessmod-rewrite

How to use htaccess to serve cache .html


RewriteEngine On
RewriteCond %{DOCUMENT_ROOT}/cache/$1-$2.html -f
RewriteRule ^(.*) /cache/$1-$2.html
RewriteRule !((.txt)|(.xml)|(.json)|(.html)|(.js)|(.mp4)|images|uploads\/(.*)|cache\/(.*)|resources\/(.*)|control\/(.*)|fonts\/(.*)|offline\/(.*)|stylesheets\/(.*)|libs\/(.*)|javascripts\/(.*))$ index.php [NC]

This is my htaccess file. It should be serving my cache files of /cache folder.

The problem I'm facing is: I have a url like site.com.br/blog/example-post/ But I am saving this cache as blog-example-post.html

Also, if no cache file found, then open index.php to control all requests. But, using cache I will decrease my server and DB requests.

Can someone please help me to replace all / from requests to - in htaccess?

Edit: a possible solution for site.com.br/blog/my-post/amp/ (saved as: blog-my-post-amp.html

RewriteEngine On
RewriteCond %{DOCUMENT_ROOT}/cache/$1-$2.html -f
RewriteRule ^([^/]+)/([^/]+)/$ /cache/$1-$2.html [NC,L]
RewriteRule ^([^/]+)/([^/]+)/([^/]+)/$ /cache/$1-$2-$3.html [L]

Update: How it is working to me now

RewriteCond %{DOCUMENT_ROOT}/cache/$1.html -f
RewriteRule ^([^/]+)/$ /cache/$1.html [L]

RewriteCond %{DOCUMENT_ROOT}/cache/$1-$2.html -f
RewriteRule ^([^/]+)/([^/]+)/$ /cache/$1-$2.html [L]

RewriteCond %{DOCUMENT_ROOT}/cache/$1-$2-$3.html -f
RewriteRule ^([^/]+)/([^/]+)/([^/]+)/$ /cache/$1-$2-$3.html [L]

RewriteCond %{DOCUMENT_ROOT}/cache/$1-$2-$3-$4.html -f
RewriteRule ^([^/]+)/([^/]+)/([^/]+)/([^/]+)/$ /cache/$1-$2-$3-$4.html [L]

RewriteCond %{DOCUMENT_ROOT}/cache/$1.xml -f
RewriteRule ^([^/]+)/$ /cache/$1.xml [L]

RewriteCond %{DOCUMENT_ROOT}/cache/$1-$2.xml -f
RewriteRule ^([^/]+)/([^/]+)/$ /cache/$1-$2.xml [L]

RewriteCond %{DOCUMENT_ROOT}/cache/$1-$2-$3.xml -f
RewriteRule ^([^/]+)/([^/]+)/([^/]+)/$ /cache/$1-$2-$3.xml [L]

RewriteCond %{DOCUMENT_ROOT}/cache/$1-$2-$3-$4.xml -f
RewriteRule ^([^/]+)/([^/]+)/([^/]+)/([^/]+)/$ /cache/$1-$2-$3-$4.xml [L]

I must fix somethings and maybe optimze the code. I will update here when it reach 100%


Solution

  • RewriteCond %{DOCUMENT_ROOT}/cache/$1-$2.html -f
    RewriteRule ^(.*) /cache/$1-$2.html
    

    The obvious issue here is you have two backreferences but only one capturing subpattern. $2 is therefore always empty. If you are expecting a request of the form /blog/example-post/, which should map to a cache file /cache/blog-example-post.html then the rule should look more like this:

     :
     RewriteRule ^([^/]+)/([^/]+)/$ /cache/$1-$2.html [L]
    

    Don't forget the L flag.


    UPDATE:

    Edit: a possible solution for example.com/blog/my-post/amp/ (saved as: blog-my-post-amp.html)

    RewriteCond %{DOCUMENT_ROOT}/cache/$1-$2.html -f
    RewriteRule ^([^/]+)/([^/]+)/$ /cache/$1-$2.html [NC,L]
    RewriteRule ^([^/]+)/([^/]+)/([^/]+)/$ /cache/$1-$2-$3.html [L]
    

    The RewriteCond (condition) only applies to the first RewriteRule directive that follows (together they form one rule). So, the second RewriteRule rewrites the request unconditionally, regardless of whether the cached file exists or not.

    You need to repeat the condition. For example:

    RewriteCond %{DOCUMENT_ROOT}/cache/$1-$2.html -f
    RewriteRule ^([^/]+)/([^/]+)/$ /cache/$1-$2.html [L]
    
    RewriteCond %{DOCUMENT_ROOT}/cache/$1-$2-$3.html -f
    RewriteRule ^([^/]+)/([^/]+)/([^/]+)/$ /cache/$1-$2-$3.html [L]
    

    Aside: The NC (nocase) flag on the first rule is superfluous since the regex ^([^/]+)/([^/]+)/$ is naturally case-insensitive anyway.