Drupal Imagecache 404 "Unable to Find" Tip

Here's a little tip for developers who encounter "unable to find" errors from Drupal's imagecache module...

Background: As a website developer, I often run a local copy of a website on my own server. I make and test changes there, before promoting those changes to the live website. Usually, my local copy is "incomplete" in that it does not have all the content and data stored on the live site. (Incomplete on purpose, as it would be a lot of overhead to keep all data and files in sync between servers.)

Problem: When my local copy is missing image files, pages will not look right, and I will see 404 errors in my Drupal log. This may seem a minor inconvenience, but it can actually cause bigger problems. Consider that a single page may have dozens of images. If all goes well, the server returns those files directly; but when they are not found, it's up to Drupal to server up a file not found page. As you probably know, each page served by Drupal entails all the overhead of Drupal's bootstrap process. So what is normally a single request to Drupal is suddenly dozens! This can really slow down a server. Plus, if your trying to step through code or find errors in logs, there's suddenly a lot of noise relative to the signal you're interested in.

Solution: Here's how I'm solving the imagecache problem. Presumably, all the images exist on a remote server (either the site's live server or perhaps a shared development machine). Since both the local and remote server are using the same software, the URL paths should easily map. So the trick is, for all those imagecache URLs, redirect the browser to the remote server. If you have this problem, give the following rewrite rule a try. You may be pleasantly surprised how much faster your pages are served.

Place this code below in your .htaccess file. Replace REMOTESERVER.com with the server that has the files.

# for images not on local copy
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} files/imagecache
RewriteRule files/imagecache(.*)$ http://REMOTESERVER.com/files/imagecache$1 [R=301,L]

Comments

Allthough I would suggest to place it in the vhost config on your local machine and not in .htaccess.

.htaccess should best be kept in the revision control. And as such, chances are that you release with this modification. Which will cause quite some overhead on the production environment :)

Dave Cohen's picture

Good point. Agreed, but it sure is easier to modify the local .htaccess. I'll be careful.

Subscribe

Dave Cohen's picture

FYI, "subscribe" won't work on this site the way it does on most drupal sites. Because here you're logged into facebook connect, but don't have a local drupal account.

It's on my todo list to make something like subscribe, without the full overhead of a full-fledged drupal account.

Dave Cohen's picture

I don't see why not. You just have to come up with exactly the right rewrite rule, which will depend on how both instances of the site are configured to store files.

I'm voting this my FAV blog post of the year so far. :-)
I'm so tired of my local host being SO out of sync with the files on the remote. I don't like syncing them and have lived with broken layouts and other issues that arise from missing images.
I was sharing this with team member Desmond Morris and he is going to use your idea as well as adding some conditional logic into .htaccess. There's your solution for keeping .htaccess in the repo.

My working example on localhost

<VirtualHost *:80>
    DocumentRoot "D:/xampp/htdocs"

<Directory "D:/xampp/htdocs/dev-example.com">
RewriteBase /dev-example.com
</Directory>

RewriteEngine On

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} sites/default/files/imagecache
RewriteRule sites/default/files/imagecache(.*)$ http://example.com/sites/default/files/imagecache$1 [R=301,L]
</VirtualHost>