Recipe 21.10 Transparently Storing Information in URLs

21.10.1 Problem

You want to store information like session IDs in the URL, but you don't want to figure out to how work around the extra data when constructing relative URLs.

21.10.2 Solution

Store the ID at the start of the URL:

Extract it with a PerlTransHandler, and store it in a pnote, a hash entry accessible by other Perl handlers in this request:

sub trans {
  my $r = shift;

  my $uri = $r->uri( );
  if ($uri =~ s{/ID/(\d{8})}{  }) {
    $r->pnotes("ID", $1);
  return DECLINED;

Restore the URL in a PerlFixupHandler:

sub fixup {
  my $r = shift;

  my $id = $r->pnotes("ID");
  if ($id) {
    $r->uri("/ID/$id" . $r->uri);
  return DECLINED;

Consult the pnote in the content handler:

use Apache::URI;

sub content {
  my $r = shift;
  my $id = $r->pnotes("ID");

  unless ($id) {
    join(('', map { int rand 10 } (1..8));
    my $uri = Apache::URI->parse($r);
    $uri->path("ID/$id" . $uri->path);
    $r->header_out(Location => $uri->unparse);
    return REDIRECT;

  # use $id

  return OK;

21.10.3 Discussion

The client thinks your pages have a URL like Your PerlTransHandler intercepts the incoming request and removes the /ID/12345678 part before Apache tries to translate the request into a file location. Just before your content handler runs, your PerlFixupHandler reinserts the ID. When your content handler calls $r->uri, it gets a URI that includes the ID.

We returned DECLINED from our PerlTransHandler and PerlFixupHandler to indicate that any other translation or fixup handlers that were installed should also be run. If we returned OK in the PerlTransHandler, Apache would not call any subsequent translation handlers. In PerlFixupHandlers, DECLINED and OK both mean a successful fixup, and that other fixup handlers should also run.

This solution doesn't look at the HTML emitted by your handler, so it only preserves the ID across relative links. If you give absolute links in your HTML (HREF="/elsewhere/"), then you'll lose the ID and have to re-establish it.

21.10.4 See Also

Recipe 12.3 of mod_perl Developer's Cookbook; Recipe 21.11