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

Hi:

I was wondering if someone can help me with this rewrite rule im trying to set up.

Im running mod perl and in my apache httpd.conf file I have a handler define as
<Location /profile> SetHandler perl-script PerlResponseHandler WEBCORE::Control::Profile->run </Location>
This works fine when the url is called as such $base_url/profile?f_id=$user_id

What I'd like to do is setup a url rewrite so I can call the profile with just $base_url/$user_id and have it map to $base_url/profile?f_id=$user_id.

I tried:
RewriteEngine On RewriteRule ^/(.*)$ /profile?f_id=$1 [R,L]
but it just trys to look for the "profile" directory/file in the file structure. I read somewhere that I need to skip the file lookup using the "PerlTransHandler" phase but I cant seem to get it to work.

If I change the url slightly in the mod rewrite it works fine. If the rule is
RewriteEngine On RewriteRule ^/u/(.*)$ /profile?f_id=$1 [R,L]
I can get to it with $base_url/u/$user_id just fine. Does anyone have any tips on where I should look? To reiterate I want the url to rewrite to a vanity url like $base_url/$user_id

Replies are listed 'Best First'.
Re: mod rewrite on mod perl handler skip trans handler phase
by perrin (Chancellor) on Dec 19, 2006 at 19:16 UTC

    What you have here is mostly a mod_rewrite question. Turn on the debugging log for mod_rewrite. It will show you what string is coming in for the URL. It's probably not what you think it is.

    Also, there is no need to use mod_rewrite for this with what you've shown so far. You could just set your mod_perl handler to respond to "Location /" instead of rewriting.

      I currently have "Location /" mapped to a Index handler which shows the index page. I was thinking about a check like:
      if location isnt mapped in httpd.conf or location doesnt exist on file system redirect to profile
      So if someone entered $base_url/$f_id ie: myspace.com/perlmonks

      if the httpd.conf doesnt contain "Location /perlmonks" and the file structure doesnt contain the "perlmonks" directory/file redirect to the profile handler.

      but not sure how the performance might be. Do you guys think this is an efficient way of doing this?

      Checking the file on the file structure would require a stat for each request which can be expensive.

      Guess an easier option is to just set up a separate url for profiles. IE: profiles.myspace.com/$f_id

        Okay, I think i finally understand your problem. You want to only intercept requests that didn't map to anything else. I don't think you can do that in any easy way with mod_rewrite. It would certainly be much easier to use a top-level prefix (like your /u example) or a virtual host (like your profiles.myspace.com example).

        One relatively simple thing you can try is to just map your perl module to the handler for 404 NOT FOUND errors. Then it will only get things that didn't match anything else. That's the easiest route, if you don't want to use the naming tricks.

Re: mod rewrite on mod perl handler skip trans handler phase
by derby (Abbot) on Dec 19, 2006 at 14:21 UTC

    Why don't you just setup your handler in such a way to interrogate path_info - if there is path_info than use that , else look at the f_id param. It looks like you're using CGI::Application so something along the lines of:

    sub do_profile { my $self = shift; my $cgi = $self->query(); my $f_id = $cgi->path_info() || $cgi->param( 'f_id' ); }

    -derby
      Can you please elaborate? If im not mistaken by using the using the path_info its just changing the way the param is passed to the module. It still doesnt solve the issue of being able to do something like:
      $base_url/$f_id example: myspace.com/$f_id
      and have it mapped to a certain perl handler (WEBCORE::Control::Profile->run). I'm not using CGI::Application, I actually have my own custom controller base class.

        Doh! Nevermind ... I thought you wanted the url to be /profile/<userid>

        In the case where you want url/<userid>, instead of mod_rewrite, you can push your location up:

        <Location /> SetHandler perl-script PerlResponseHandler WEBCORE::Control::Profile->run </Location>
        And then inspect the url - if it begins with profile, get the params, else break apart the url to get the userid.

        -derby