views:

514

answers:

3

I know that we can easily base a RewriteCond on any http request header. But can we check (some of) the response headers that are going to be sent? In particular, the Last-modified one?

I want to rewrite a url only when the Last-modified date is older than 30 minutes and I'm trying to avoid the overhead of delegating that check to a php file every single time a file from that directory is requested.

Thanks in advance!

+3  A: 

No, that’s not possible. But you could use a rewrite map to get that information from a program with less overhead than PHP, maybe a shell script.

Here’s an example bash script:

#!/usr/bin/env bash
while read line; do
    max_age=${line%%:*}
    filename=${line#*:}
    if [[ -f $filename ]]; then
        lm=$(stat -f %m "$filename")
        if [[ $(date +%s)-$lm -le $max_age ]]; then
            echo yes
        else
            echo no
        fi
    else
        echo no
    fi
done

The declaration of the rewrite map needs to be placed in your server or virtual host configuraion file as the program is just started once and then waits for input:

RewriteMap last-modified-within prg:/absolute/file/system/path/to/last-modified-within.sh

And then you can use that rewrite map like this (.htaccess example):

RewriteCond %{last-modified-within:30:%{REQUEST_FILENAME}} =yes
RewriteRule ^foo/bar$ - [L]
RewriteRule ^foo/bar$ script.php [L]
Gumbo
nice solution ya got there.
meder
derobert
Wow, that's smart! Thanks a lot for your time. However, what about derobert's objection above?
Michelle
@derobert: Ah, sorry, forgot about that. The program is just started once and then waits for input on SDTIN.
Gumbo
I have to admit that it didn’t work for me. But that’s how it would be done.
Gumbo
Even if your bash script is staying running, you're still spawning at least a `stat` and a `date` for each request. BTW: Shouldn't that be `[ ... ]` not `[[ ... ]]`?
derobert
A: 

The outbound headers do not exist until much later than mod_rewrite is acting. There also isn't any file-modification-time checking functionality built into mod_rewrite, so the closest you'd get using it is making a RewriteMap of the External Rewriting Program variety to find out whether the file in question has been modified.

If I understand your application correctly, you could also look into having a cron job delete files in that directory that are older than 30 minutes, and then rewriting on a file-nonexistence condition.

chaos
Yeap, obviously. But the Last-modified header does exist at that time, so I thought that perhaps there's something for that. I guess there isn't :-(As for the cron, that's exactly what I'm trying to avoid.
Michelle
A: 

Have you considered using mod_proxy, mod_cache, and/or squid? It sounds like you're trying to roll your own caching...

derobert
Yeap, I'm trying to cache some php/gd generated images and recreate them every 30 minutes, if needed (=if someone actually requests them). You think mod_proxy, mod_cache or squid can help? I've never really looked into them to be frank. I always thought they are for more complicated things.
Michelle
Yes, you're doing web caching, and that's exactly what those are intended for. Naturally, you should only bother with this optimization if it matters (e.g., you have the traffic volume to require it).
derobert