derby has asked for the wisdom of the Perl Monks concerning the following question:

Fellow monks,

I have a rather obscure (to me) problem. I'm working on a prototype with mod_perl and am running into an issue with progogating path_info. Here's a general overview of the prototype:

A URL such as http://www.myserver.com/app/id should default to http://www.myserver.com/app/id/step_one. I have a fixup handler on app that handles this correctly (??? - in that step_one is added to path_info).

The HTML generated contains a real generic form action - "step_two."

Here's the issue, when invoked as http://www.myserver.com/app/id/step_one - the id is propogated and step_two is invoked properly (/app/id/step_two); however, when invoked as http://www.myserver.com/app/id, the id is not propogated and the action is incorrectly invoked (/app/step_two).

I'm not sure what to set in the fixup handler to properly propogate the id when modifying the path info. Below is the the handler.

sub handler { my $r = shift; my( $id, $step ) = (split( /\//, $r->path_info ))[1,2]; if( ! $step ) { $step = "step_one"; # Seems to have no bearing on $ENV{REQUEST_URI} my $ruri = $r->uri . "/" . $step; $r->uri( $ruri ); $r->subprocess_env( REQUEST_URI => $ruri ); $ENV{REQUEST_URI} = $ruri; # Modify path_info my $pinfo = $r->path_info . "/" . $step; $r->path_info( $pinfo ); $r->subprocess_env( PATH_INFO => $pinfo ); $ENV{PATH_INFO} = $pinfo; } ....

Of course, this is a problem with my not understanding how a relative url is properly resolved (and where in the apache lifecycle I can influence it). I also tried setting SCRIPT_URI, SCRIPT_NAME and SCRIPT_URL via subprocess_env and ENV mangling.

Any ideas?

-derby

Replies are listed 'Best First'.
Re: mod_perl and propogating path_info
by derby (Abbot) on Mar 27, 2003 at 15:49 UTC
    All right. I'll take a stab at answering my own question. What I was hoping to do was set the base url in the response so my templates didn't need to worry about it and could just use a real generic "step_two" action. However, looking into it more (and duh! thinking about it), resolving relative urls is a pure client operation - there's nothing that I can find that will allow me to set a base url in the response header - only in the content. I've come up with the following solutions:

    • simplify fixuphandler to just redirect to /step_one url when step is missing.
    • inject id into params as and let the templates prepend it to generic action
    • set ENV var and let the templates prepend ...
    • use param or ENV not as action but for setting "<base>" tag.

    I'm leaning to just redirecting ...

    -derby

    update

    • instead of redirecting in the fixuphandler, use mod_rewrite to redirect

Re: mod_perl and propogating path_info
by perrin (Chancellor) on Mar 27, 2003 at 18:35 UTC
    Sounds like you're looking for the PerlTransHandler. There is an example in the docs there.
      I considered PerlTransHandler because the problem sounds an awful lot like URL re-writing (ala sessionids). I didn't mention it but there are other apps running under the myserver.com domain. Since a PerlTransHandler cannot be within a Location, Directory or Files section and I didn't want to burden the other apps, I choose not to use a PerlTransHandler.

      -derby

        Well, it's essentially the same as using mod_rewrite if you already have mod_perl compiled in. You could also use $r->internal_redirect($new_uri) for this.
Re: mod_perl and propogating path_info
by Lhamo Latso (Scribe) on Mar 27, 2003 at 19:08 UTC

    After reading in LStein's book, your use of $r->subprocess_env seems to be the wrong approach. "Changes made to the environment table only persist for the length of the request. The table is cleared out and reinitialized at the beginning of every transaction." (pg.455)

    On pg. 437, it is noted that changing the path_info() requires syncing the uri() to the update. As in:

    my $path_info = $r->path_info; my $uri = $r->uri; my $orig_uri = substr $uri, 0 length($uri) - length($path_info); $r->path_info($path_info . $step); $r->uri($orig_uri . $r->path_info);