Drupal book


Yowza! Lookee here! And here.

Serving static files with Apache and directories with url aliasing in Drupal using mod_rewrite

A common task is to move a static site to a Drupal site. For example, you might have

/site/
/site/2004
/site/2004/index.html
/site/2004/page_1.html
/site/2004/page_1_image.jpg

You think to yourself, "I'll just leave the image files on the existing filesystem. They don't really need to go into Drupal anyway." So after your content migration is complete your content is in Drupal but you've got the following left in the directory:

/site/
/site/2004
/site/2004/page_1_image.jpg

What happens when someone tries to go to http://example.com/site/2004/ ?

They get either a directory listing or a Forbidden message, depending on how you have Apache's Indexes directive set for that directory or its parents. But you don't want that! You want it to pass through to Drupal, where you've created a url_alias entry so that all the old URLs, including directory URLs get mapped to Drupal nodes.

Suddenly you come upon a clever idea. Why not just edit the relevant portion of Drupal's .htaccess file to stop Drupal from aborting the rewrite if the path points to a directory?

  # Rewrite current-style URLs of the form 'index.php?q=x'.
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]

becomes

  # Rewrite current-style URLs of the form 'index.php?q=x'.
  RewriteCond %{REQUEST_FILENAME} !-f
#RewriteCond %{REQUEST_FILENAME} !-d
  RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]

All is happy. Happy happy. Your files are being served, Drupal is handling requests with url aliasing, but wait! What's this? Going to

/site

Results in a Bad Request error from Apache. But

/site/

works fine. What's going on? It's a long story, but basically the DirectorySlash magic is happening before mod_rewrite can get ahold of the request (because mod_dir runs before mod_rewrite). Here's the answer:

 
# Fake out DirectorySlash so that Drupal can serve up the directory.
# Don't use [L] here as we pass on to the next rule.
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d
RewriteCond %{REQUEST_URI} !/$
RewriteRule ^(.+)$ $1/

# Allow apache to serve up existant files directly but pass
# everything else to Drupal, including 'directory' requests
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.+)$ index.php?q=$1 [L,QSA]

Thanks to noodl in #apache for this solution. chx notes that you need [L, QSQ] instead of [QSA] on your last rewrite rule.

Note that this is an either-or situation. You can't serve some former-directories-which-are-now-URL-aliases from Drupal and leave other directories with index.html files in them and have Apache serve those. When you try to hit http://www.example.org/somedirectory/ you will not get http://www.example.org/somedirectory/index.html; instead you will get Drupal's 404 handler.

Topic: 

Safari contextual menu for applying Drupal patches

I wanted an easy way to test patches, so here's what I did.

Downloaded OnMyCommand.

Copied the OMCEdit application folder to Applications.

Ran the script Install OnMyCommandCM (I checked it out in Script Editor first.)

Logged out and logged back in.

Followed this tutorial.

I created a contextual menu item named Apply patch to Drupal installation with the following code:

#!/bin/bash
DRUPAL_HOME=/Library/WebServer/Documents/
cd $DRUPAL_HOME
touch drupaltemp
rm -R drupaltemp
cp -R drupal drupaltemp
cd drupaltemp
osascript -e 'tell Application "Safari"' -e 'get source of document 1' -e 'end tell' | perl -0ne 'print "$1\n" while (/a href="(http:\/\/drupal.org\/files.*?)">.*?<\/a>/igs)' | tail -1 | sed "s/\(.*\)/--url \1/" | curl --config - > patch
bbedit patch
patch -p0 < patch

Now when I right-click on an issue and choose Apply patch to Drupal installation, the script:

  • Creates a working copy of Drupal.
  • Obtains the source of the current page from Safari.
  • Parses out URLs that designate patches (begin with drupal.org/files).
  • Find the last one, since there may be multiple patches in the issue.
  • Download the patch.
  • Open the patch in BBEdit.
  • Apply the patch to the working copy of Drupal.

Note: this is actually a workaround. I wanted to modify Safari's contextual menu for links, but was unable to find a way to hook in.

Sadly, this will probably not increase the number of patches I review, as it's not really the patching that takes time. This was more of an, I can't sleep...I wonder if I could create a contextual menu that... kind of a project.

ImageLabeler and tagging games

The biggest obstacle to implementing metadata-driven systems is getting those who have the best knowledge to actually enter the metadata. Entering metadata for content is widely seen as a chore, and that grumbling sound you hear is the sound of all those users whose managers have made the metadata mandatory.

I just stumbled across Google Image Labeler. It turns image metadata entry into a game, where you're paired with another player and compete to produce matching metadata for a given image. (I'm sure Google doesn't throw away the metadata that doesn't match, either.)

There's a good explanation by Michael Mahemoff at Ajaxian.com.

Topic: 

Pages

Subscribe to SysArchitects RSS