On Apache 2.4, Having a bunch of mixed SEO friendly and dynamic URLs on an ecom site I want to implement a simple caching system for my blog posts and product pages. First I want to have md5(REQUEST_URI+QUERY_STRING) and then load the prerendered /cache/md5hashumfile.html that's all.

Here is my htaccess code:

    RewriteEngine on 
    RewriteBase /subfolder/
    RewriteCond "expr=%{DOCUMENT_ROOT}/subfolder/cache/%{md5:%{REQUEST_URI}?%{QUERY_STRING}}\.html" -f 
    RewriteRule ^(.*)$ /cache/%{md5:%{REQUEST_URI}?%{QUERY_STRING}}\.html [L]

When I do

Header set foo-doc-root "expr=%{DOCUMENT_ROOT}/subfolder/cache/%{md5:%{REQUEST_URI}?%{QUERY_STRING}}\.html"
foo-doc-root:   /home/user/public_html/subfolder/cache/f427ac3f86b93f6869ef8c2ce847dbd6.html

I can verify in my headers the path is correct and the file exists exactly where I expect it.

I can verify the md5 sum of my URL been the same md5

Header set foo-uri "expr=%{REQUEST_URI}?%{QUERY_STRING}\.html"

Where can it be improved?

  • "Where can it be improved?" - But I assume it's not working at all at present?
    – MrWhite
    Commented Mar 29, 2023 at 15:48
  • No, unfortunately it does not.
    – nikis
    Commented Mar 29, 2023 at 16:05
  • In the RewriteCond I think I would capture the specific parts instead of repeating the same expression in the rewriterule . RewriteCond "expr=%{DOCUMENT_ROOT}/subfolder/(cache/%{md5:%{REQUEST_URI}?%{QUERY_STRING}}\.html)" -f and then RewriteRule ^ /%1 [L] Commented Mar 29, 2023 at 16:59
  • 1
    @DanielFerradal I think that's the right idea (you can't use expressions in the RewriteRule anyway). However, there are some more fundamental errors here . The syntax for using expressions in a RewriteCond directive is not correct and I don't believe you can create arbitrary capturing groups like this - this is a regex thing, so a separate regex-condition is required to simply capture the result of the md5() function. I've explained some of this in my answer.
    – MrWhite
    Commented Mar 29, 2023 at 17:44
  • Just curious... at what point do you create the cache file? (How do you expire/delete the cache?)
    – MrWhite
    Commented Mar 29, 2023 at 17:45

1 Answer 1

RewriteBase /subfolder/
RewriteCond "expr=%{DOCUMENT_ROOT}/subfolder/cache/%{md5:%{REQUEST_URI}?%{QUERY_STRING}}\.html" -f 
RewriteRule ^(.*)$ /cache/%{md5:%{REQUEST_URI}?%{QUERY_STRING}}\.html [L]

You have a few errors here:

  • You are setting RewriteBase /subfolder/, however, this is not being used by this rule since you are using a root-relative substitution string (starting with a slash). Consequently, it looks like you are trying to rewrite to the wrong URL-path. ie. /cache/... instead of /subfolder/cache/.... EDIT: I assume this rule is being used in a directory (or .htaccess) context, otherwise the use of RewriteBase here is wholly invalid.

  • RewriteCond "expr= - This is not the correct syntax when using an Apache expression inside a RewriteCond directive. It looks like you are using mod_headers syntax. With mod_rewrite the TestString (1st argument) should be expr, then the CondPattern (2nd argument) is the expression. eg. RewriteCond expr expression.

  • -f (at the end) - Again, this is not the correct syntax. When using an Apache expression, the -f operator is part of the expression (CondPattern) and must come first. (Ordinarily, when using normal mod_rewrite syntax, the -f "test" is the CondPattern itself.)

  • You can't use expression syntax in the RewriteRule substitution string. You can, however, use backreferences to captured groups (regex) in the preceding conditions. So, calculate/capture the md5 hash in a condition and use a backreference instead.

Try the following instead:

RewriteBase /subfolder/
RewriteCond expr "-f '%{DOCUMENT_ROOT}/subfolder/cache/%{md5:%{REQUEST_URI}?%{QUERY_STRING}}.html'"
RewriteCond expr "'cache/%{md5:%{REQUEST_URI}?%{QUERY_STRING}}.html' =~ /(.+)/"
RewriteRule ^ %1 [L]

Additional notes:

  • ^(.*)$ - No need to captured the URL-path since you are using the REQUEST_URI server variable instead.
  • No need to backslash-escape literal dots in the RewriteRule substitution string - this is an "ordinary string", not a regex.
  • I've removed the slash prefix from the substitution string so that it will now take into account the RewriteBase.
  • The purpose of the 2nd RewriteCond directive is simply to capture the md5 hash file name (and file-path) to then use in the RewriteRule substitution using the %1 backreference.

The above does require two calls to the md5() function. You could try the following instead to reduce this to one (and to also remove the dependency on RewriteBase, since you are having to hardcode the /subfolder in the expression anyway):

RewriteCond expr "'/subfolder/cache/%{md5:%{REQUEST_URI}?%{QUERY_STRING}}.html' =~ /(.+)/"
RewriteCond expr "-f '%{DOCUMENT_ROOT}%1'"
RewriteRule ^ %1 [L]

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .