Generic Gravatar Cache

About

Gravatar Cache is a generic URL-based caching system for Gravatar, the "Globally Recognized Avatar", which are commently used in blog comments.

Gravatar is an interesting application -- it assigns an avatar, a 80 by 80 pixels image, to an email address, which can be displayed in commnunity/collaboration applications where users' emails are entered. It is often implemented by blogsites to display next to contributors of the comments. Designed and implemented by Tom Werner, gravatar adds lively colours to otherwise boring blog comments.

There are many ways to implement gravatars in blogsites/CMS. The easiest way is to construct the gravatar URL using md5(email address) plus a few other parameters. Some implementations are more sophisticated, like gravatars 2 for WordPress which also implements local cache.

Like all centralised web applications, distributed caching helps to reduce the stress on the centralised servers, both CPU resources and bandwidth. It helps the service to deliver faster, and can continue to serve cached content when centralised server can no longer be contacted. The same can be said about gravatar cache.

Gravatars 2 is actually quite a good implementation for WordPress. However, the issue is -- it is very WordPress-specific, and we cannot easily bring the benefit of caching to other CMS, especially those that are not based on PHP.

Thus a few nights of hacking gave birth to this little project -- generic Gravatar Cache. It is a simple caching system for gravatar that works totally on URL, and can be easily integrated with many publishing systems.

Download

Features

  • Single PHP file installation with minimal configuration.
  • Easy integration with blogging software/CMS -- just point the URL of the image to your cache.
  • Positive caches, i.e. email addresses that associate with actual gravatars, are fetched directly by web server as local files, and PHP does not need to be invoked.
  • Negative caches, i.e. email addresses that do not associate with gravatars, can be optionally configured with a different expiry.
  • Positive caches are stored in files. Negative caches can be stored in either files, DBM or SQLite database.

Usage

  1. Download gravatar-cache, and install it into a web directory. It does not need to be at the root of a domain/subdomain. After you unpack the tarball (or checkout the subversion repository), you should have the following files:

    + gravatar-cache/
    +-- cache/
    +-- profile/
    +-- index.php
    
  2. Move the top directory "gravatar-cache" (and all its content) to whereever you want your cache to be. You also need to make sure the directory "cache" is writable by the web server/PHP processes. For example,

    $ chmod a+w gravatar-cache/cache
    

    You don't need to do anything if your PHP is executed in suexec CGI (for example on DreamHost.

  3. From this point forward, we are assuming that your gravatar cache is installed at http://mysite/gravatar-cache/.

    You need to configure your web server to pass cache-miss requests to index.php. For Apache, you nee to have mod_rewrite enabled (which most hosting companies do), and create a .htaccess file and put it inside the gravatar cache directory.

    <IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule . /gravatar-cache/index.php [L]
    </IfModule>
    

    If you are using lighttpd, add the following into your lighttpd.conf file.

    $HTTP["host"] == "mysite" {
        $HTTP["url"] =~ "^/gravatar-cache/" {
            server.error-handler-404 = "/gravatar-cache/index.php"
        }
    }
    

    Obviously you need to adjust "mysite" and "gravatar-cache" to where you have installed your cache.

  4. Now you need to create "profile" for each configuration/blogsite you wish to use the cache. For example for "myblogsite" I would like to have gravatars at 64x64 pixels, rated PG and default to http://mysite/default-gravatar.png, I shall create a "profile configuration" named "myblogsite.php" and place it inside the "profile" directory.

    <?php
    $config['default'] = 'http://mysite/default-gravatar.png';
    $config['rating'] = 'PG';
    $config['size'] = 64;
    ?>
    
  5. To access the gravatar, you'll need to use this URL:

    http://mysite/gravatar-cache/cache/<profile name>/<gravatar ID>
    

    Gravatar ID is the md5 digest of email address. With the example above, to download the gravatar with my email address would be

    http://mysite/gravatar-cache/cache/myblogsite/6728f59b3c3cf137e92361605d7b2159
    

    If gravatar exists for that email address, then subsequent request to that URL will become a direct file access from web server, and no PHP needs to be invoked. If gravatar does not exist, it will respond with a 302 redirect to the default gravatar in the profile configuration. If negative cache is enabled (default), subsequent request will still invoke PHP, but will be a quick lookup without contacting the gravatar server.

  6. You also need to implement a "cron job" to periodically clean up the cache. For example if you want to do it once a day at 12 midnight, fire up crontab -e and issue this command to the gravatar cache.

    0 0 * * * wget -O /dev/null -o /dev/null http://mysite/gravatar-cache/?purge=1
    

Configuration

There are two types of configuration files -- global configuration and profile configuration. You can have at most one global configuration file (config.php in the same directory as index.php), and you need one profile configuration file (profile/<profile name>.php) for each profile you wish to have. The format are exactly the same, with a list of

$config['<option>'] = <value>;

Here are a list of options.

border (no default)

From the gravatar website, "hexadecimal value of a 1px border to be overlaid on the gravatar". For example "FF0000 for red".

default (no default)

From the gravatar website, "full URL, protocol included, of a GIF, JPEG, or PNG image that should be returned if either the requested email address has no associated gravatar, or that gravatar has a rating higher than is allowed by the 'rating' parameter."

You do not need to encode the URL. If this parameter is not specified, gravatar cache will return a 1 pixel GIF instead.

rating (default='PG')

From the gravatar website, "highest rating (inclusive) that will be returned". It can be either 'G', 'PG', 'R' or 'X'.

size (default=64)

From the gravatar websitem "desired width and height of the gravatar. Valid values are from 1 to 80 inclusive".

proxy (no default)

Proxy server to use to access the gravatar website, if your web server does not have direct out-bound access (rare). It is in the form of "http://proxy-server:port". Works only when "curl" is enabled in PHP.

pos_expiry (default=604800)

Number of seconds for positive cache to expire. Default is 7 days, as people don't usually change gravatars that often. Note that this value is not checked in a cache-hit, as PHP is not invoked.

neg_expiry (default=43200)

Number of seconds for negative cache to expire. Default is 12 hours. Set it to 0 if you do not wish to have negative cache (which might be wise). Note that this value is always checked when a cache-miss occurred.

neg_handler (default='file')

Handler for negative cache. Value can be either 'file', 'dbm', 'mysql' or 'sqlite'. For 'file', it creates one file for every negative gravatar ID, which is not ideal if your web root is on a optimised file system (or is NFS mounted). 'dbm' uses dbm-style databases. 'sqlite' uses SQLite functions. Both requires modules to be built in PHP.

Handler 'mysql' is new in 0.2 and uses MySQL as backend which is suitable for high-volume cache as MySQL handles concurrency much better than SQLite. It requires configuration option 'mysql' also been set. Database needs to be created first and initialised with mysql.sql in the distribution.

mysql

Used when neg_handler is 'mysql'. This option sets the MySQL connection paramter using an URI format:

mysql://<username>:<password>@<hostname>/<database>

(Note on negative expiry. While negative responses can be cached, I fear that it might be abused. Since the caching system is URL based, someone can potentially write a script to scan through every combination of md5 digest space (2128) and bloat your negative cache database.)

Implementations

Basically you just need to point the source of image to your own gravatar cache. The only computation needs to be done is the md5 digest of the email addresses.

PHP

For example in PHP based CMS/blogging software:

<img src="http://mysite/gravatar-cache/cache/myprofile/<?php echo md5($email_address); ?>"/>

Support

If you have any question regarding Generic Gravatar Cache, please use the FuCoder support forum to post enquiries.

History

  • 0.2 (2007-07-20)
    • Add mysql backend support for handling negative responses.
    • Remove fopen_url based method as it handles 302 automatically but we would like to have the status returned instead.
  • 0.1.1 (2006-12-25)
    • Add support for X-send-file (in Apache and Lighttpd).
    • Fix default gravatar issue in Gravatar2
  • 0.1 (2006-05-27)
    • Initial implementation.