Clean URLs with Lighttpd

Last modified: April 9, 2009 - 05:50

For those who have stepped up a notch in performance and moved from Apache to Lighttpd, you need to fix you clean URLs. There are two ways to do so:

Using url rewrites

First you can use the following configuration for Lighty's mod_rewrite module:

url.rewrite-final = (
  "^/system/test/(.*)$" => "/index.php?q=system/test/$1",
  "^/([^.?]*)\?(.*)$" => "/index.php?q=$1&$2",
  "^/([^.?]*)$" => "/index.php?q=$1",
   "^/rss.xml" => "/index.php?q=rss.xml"
)

The first line ensures that Drupal's clean URL check (when saving Settings) succeeds (Drupal makes an HTTP request for a path of the form /system/test/yLgnwqqUu5cWnvPi4Hrz.png). It's a special case that must be handled separately (read on for the reason).

The two following lines let Drupal handle any URL that doesn't contain a dot. This is significant because we can assume, fairly confidently, that addresses like /node/add are Drupal URLs, but addresses such as /themes/bluemarine/style.css are physical files. So the above configuration will work for all cases where this assumption holds true; if there are exceptions to the rule, they can be manually added to the rewrite configuration.

The last line handles the important exception of rss.xml, a Drupal URL that contains a dot.

See also the related discussion at http://drupal.org/node/20766

Using mod magnet

Second you can use lighty's mod magnet module together with a simple lua scripts. Have a look at the tutorials
http://realize.be/drupal-lighttpd-clean-urls-made-easy or
http://more.zites.net/lighttpd_and_drupal_clean_urls_flexible

This way has the advantage that there are no problems with dots.

Addition of search-related rewrite

shogsbro - May 28, 2006 - 10:39

I use the following rule in my lighttpd config:

url.rewrite-once = (
"^/system/test/(.*)$" => "/index.php?q=system/test/$1",
"^/search/node/(.*)$" => "/index.php?q=search/node/$1",
"^/([^.?]*)\?(.*)$" => "/index.php?q=$1&$2",
"^/([^.?]*)$" => "/index.php?q=$1"
)

lighttpd config

adub - September 22, 2006 - 15:35

Bear in mind that you can't necessarily just cut and paste the examples. I'm running lighty as my local dev server for several sites on a windows machine and file downloads are set to private. The local path for the server is c:/lighttpd/ and each site is c:/lighttpd/sitename-here/htdocs/. I used the following config:

url.rewrite-final = (
  "^/sitename-here/htdocs/system/test/(.*)$" => "/sitename-here/htdocs/index.php?q=system/test/$1",
  "^/sitename-here/htdocs/([^.?]*)\?(.*)$" => "/sitename-here/htdocs/index.php?q=$1&$2",
  "^/sitename-here/htdocs/([^.?]*)$" => "/sitename-here/htdocs/index.php?q=$1",
   "^/sitename-here/htdocs/system/files/(.*)$" => "/sitename-here/htdocs/index.php?q=system/files/$1",
  "^/sitename-here/htdocs/search/node/(.*)$" => "/sitename-here/htdocs/index.php?q=search/node/$1"
)

New version offers less hacky approach

willmoy - January 10, 2007 - 01:24

Since lighttpd 1.4.12 and mod_magnet it has been possible to implement this in a more sophisticated manner (i.e. so dots in a non-file URL won't break it). Full details to follow when I've gone through it.
Docs here: http://trac.lighttpd.net/trac/wiki/Docs%3AModMagnet#complex-rewrites

This is how to do it

willmoy - January 14, 2007 - 12:01

In lighttpd.conf:
magnet.attract-physical-path-to = ( "/etc/lighttpd/rewrite_drupal.lua" )

(Also, make sure mod_magnet appears and is not commented out in the modules list).

/etc/lighttpd/rewrite_drupal.lua:
attr = lighty.stat(lighty.env["physical.path"])
if (not attr) then
lighty.env["uri.query"] = "q=" .. lighty.env["uri.path"]
lighty.env["uri.path"] = "/index.php"
lighty.env["physical.rel-path"] = lighty.env["uri.path"]
lighty.env["physical.path"] = lighty.env["physical.doc-root"] .. lighty.env["physical.rel-path"]
end

I have rewrite_drupal.lua owned by root and chmod 755.

You need lighttpd >= 4.1.12, configured --with-lua. Debian users, this means you need to be running Etch (currently testing) with lighttpd-mod-magnet installed.

Where'd you get lighty.stat

nezroy - March 25, 2007 - 11:09

Where'd you get lighty.stat from? Is that something you pulled in from LuaFileSystem?

EDIT: Ah, I see, it's supposed to be part of mod_magnet since 1.4.13. Except it isn't in the Ubuntu 1.4.13 mod_magnet package for some reason...

EDIT2: For anyone else coming along, the default Edgy Ubuntu 1.4.13 package for lighttpd is actually only RC13, so I guess that's why lighty.stat isn't in there. The newer packages (full 1.4.13 release) work fine.

mod_magnet script and pagers?

leafish_paul - October 17, 2007 - 16:19

Hi - currently playing with mod_magnet and your lua code (cheers!) - seem to be experiencing problems with pagers, eg:

http://example.com/node?page=2

(which is perhaps expanding to http://example.com/?q=node?page=2 instead of http://example.com/?q=node&page=2). Any ideas?

---
paul byrne
paul.leafish.co.uk | www.leafish.co.uk

It would be a problem if there is another query string already

emzi - January 14, 2008 - 22:00

more safe way to rewrite url will look like this:

attr = lighty.stat(lighty.env["physical.path"])

-- we couldn't stat() the file so we need to rewrite
if (not attr) then

    -- physical path should be a Drupal's main index.php
    lighty.env["physical.path"] = lighty.env["physical.doc-root"] .."index.php"

    -- if there is another query string already, prepend it with ours
    if(lighty.env["uri.query"]) then
        lighty.env["uri.query"]="q="..lighty.env["physical.rel-path"].."&"..lighty.env["uri.query"]
    else
        -- initial query string was empty, we generate our own
        lighty.env["uri.query"]="q="..lighty.env["physical.rel-path"]
    end
end

/Michael

mod-magnet on ubuntu

zanlus - March 17, 2008 - 19:06

If you are running Ubuntu Feisty, the mod-magnet is a separate package: lighttpd-mod-magnet.

I followed the instructions at http://nordisch.org/2007/2/6/drupal-on-lighttpd-with-clean-urls
Worked like a charm, even on virtual hosts.

Hope this helps someone with this.

Zanlus

I vouch

Malthus - November 26, 2008 - 00:53

The linked configuration works great. Unfortunately, it only works if drupal is in the webroot and not a subdirectory. It does work great though.

Simpler url rule that works with dots

Malthus - November 26, 2008 - 01:03

For setups with drupal in subdirs:
url.rewrite = ( "^/([^/]*)/(?!(misc|theme|module|site))([^?]*)\??(.*)$" => "/$1/index.php?q=$3&$4" )

For drupal in the webroot (untested, but should work):
url.rewrite = ( "^/(?!(misc|theme|module|site))([^?]*)\??(.*)$" => "/index.php?q=$2&$3" )

It guesses the static files (images, css, js, uploaded files[usually in the site subdir]) by not matching on the subdirectories were these are usually located (rather than by skipping paths with a dot. It works with appended query strings (e.g. destinations for redirects and pager links).

I've described a flexible

fago - February 11, 2009 - 17:32

I've described a flexible way to support clean-URLs by using the lua-script. So there also no troubles with dots :)
http://more.zites.net/lighttpd_and_drupal_clean_urls_flexible

Woohoo!

fizk - April 11, 2009 - 01:21

Thanks fago, this is the only lua script that worked for me right away, no modifications.

Ignore this post

dropchew - May 9, 2009 - 08:22

Using the mod-rewrite,

With dots and @s it will display 404 error.

Edit. @s works too, pardon me.

 
 

Drupal is a registered trademark of Dries Buytaert.