![]() |
John VanDyk has been innovating with information technology for more than 20 years. Read more... |
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.
- Log in to post comments
Comments
static to dynamic
Hi John
I have read your book and I appreciate your work, but I have not yet purchased it but I would appreciate a moment.
I remember checking a link you suggested, I believe it was in a highlighted box, but I did not save it. It was for a Microsoft product which contains an Apache server, php, drupal, joomla, mysql and other tools so that I can work on my sites on my local pc then upload them to the live site.
Would you share that with me again.
I thank you in advance.