mod_rewrite provides virtually any functionality you can think of for manipulating URLs. Because of its highly generalized nature and use of complex regular expressions, it is not easy to use and has a high learning curve.

With the help of PerlTransHandler, which is invoked at the beginning of request processing, we can easily implement everything mod_rewrite does in Perl. For example, if we need to perform a redirect based on the query string and URI, we can use the following handler:

package Apache::MyRedirect;
use Apache::Constants qw(OK REDIRECT);
use constant DEFAULT_URI => '';

sub handler {
    my $r    = shift;
    my %args = $r->args;
    my $path = $r->uri;

    my $uri = (($args{'uri'}) ? $args{'uri'} : DEFAULT_URI) . $path;

    $r->header_out->add('Location' => $uri);

    return OK;

Set it up in httpd.conf as:

PerlTransHandler Apache::MyRedirect

The code consists of four parts: retrieving the request data, deciding what to do based on this data, setting the headers and the status code, and issuing the redirect.

So if a client submits the following request:

the $uri parameter is set to, and the request will be redirected to that URI.

Let's look at another example. Suppose you want to make this translation before a content handler is invoked:

/articles/10/index.html  =>  /articles/index.html?id=10

The TransHandlershown in Example A-4 will do that for you.

Example A-4. Book/

package Book::Trans;
use Apache::Constants qw(:common);
sub handler {
    my $r = shift;
    my $uri = $r->uri;
    my($id) = ($uri =~ m|^/articles/(.*?)/|);
    return DECLINED;

To configure this handler, add these lines to httpd.conf:

PerlModule Book::Trans
PerlTransHandler Book::Trans

The handler code retrieves the request object and the URI. Then it retrieves the id, using the regular expression. Finally, it sets the new value of the URI and the arguments string. The handler returns DECLINEDso the default Apache TransHandler will take care of URI-to-filename remapping.

Notice the technique to set the arguments. By the time the Apache request object has been created, arguments are handled in a separate slot, so you cannot just push them into the original URI. Therefore, the args( ) method should be used.