You are viewing a plain text version of this content. The canonical link for it is here.
Posted to modperl@perl.apache.org by Eric Lease Morgan <er...@infomotions.com> on 2009/07/22 03:32:20 UTC

rewriterule, location, and perlhandler

How do I get Apache's RewriteRule, Location, and PerlHander to work  
nicely together?

I have a the following Hello World mod_perl module:

   package Apache2::Alex::SemanticWeb;

   use Apache2::Const -compile => qw( OK );
   use strict;

   sub handler {

     my $r = shift;
     $r->content_type( 'text/html' );
     $r->print( 'hello, world!' );
     return Apache2::Const::OK;

   }

   1;

I then touch a file named semantic-web.cgi.

I then add a Location directive to httpd.conf:

   <Location /sandbox/semantic-web.cgi>
     SetHandler perl-script
     PerlHandler Apache2::Alex::SemanticWeb
   </Location>

I then use my browser to go to the following URL, and it returns  
"hello, world!":

   http://infomotions.com/sandbox/semantic-web.cgi

Great and wonderful.

I now want to implement a RewriteRule -- a la a "cool" linked data URL  
-- to redirect URLs with a specific shape to SemanticWeb.pm, and I use  
the following:

   RewriteRule ^/etexts/id/(.*) /sandbox/semantic-web.cgi?id=$1

In other words, all request starting with /etexts/id should be  
redirected (rewritten) to go to semantic-web.cgi. Unfortunately, all  
requests go directly to the touched file and not to my Perl package;  
the Location directive seems by-passed. When I remove semantic-web.cgi  
from my file system I get a 404 error (file not found).

What am I doing wrong? Does an actual file need to exist in order for  
mod_perl to find it? How should I edit httpd.conf so I can: 1) rewrite  
GET requests, and 2) execute the result in a mod_perl module?

-- 
Eric Lease Morgan
Infomotions, Inc.



Re: rewriterule, location, and perlhandler

Posted by Eric Lease Morgan <er...@infomotions.com>.
On Jul 22, 2009, at 10:27 AM, Torsten Foertsch wrote:

>> If you want, it's actually possible to take this even further and  
>> remove rewrite completely.
>>
>> <Location /etexts/id/>
>>   SetHandler perl-script
>>   PerlHandler Apache2::Alex::SemanticWeb
>> </Location>
>>
>> Then alter your handler's code to parse $r->uri and extract
>> everything after $r->location. (or you can use $r->path_info, if the
>> /etexts/id/ actually exists in your document root).  That'll give you
>> the same thing that rewrite is currently stuffing into your id
>> argument.
>
> Never use path_info unless you are very sure it is what you want.
> Path_info is made for CGI scripts where $r->filename points to the  
> file
> containing the script....
>
> substr($r->uri, length $r->location) is almost always what you need.


These two things represent a very elegant solution that I have already  
implemented. Cool. Thanks!

-- 
Eric Lease Morgan


Re: rewriterule, location, and perlhandler

Posted by Torsten Foertsch <to...@gmx.net>.
On Wed 22 Jul 2009, Adam Prime wrote:
> Eric Lease Morgan wrote:
> > On Jul 22, 2009, at 12:05 AM, Adam Prime wrote:
> >
> > By first changing my Location directive to the following:
> >
> >  <Location /sandbox/semantic-web/>
> >    SetHandler perl-script
> >    PerlHandler Apache2::Alex::SemanticWeb
> >  </Location>
> >
> > And then changing my RewriteRule to this:
> >
> >   RewriteRule ^/etexts/id/(.*) /sandbox/semantic-web/?id=$1
> > [passthrough]
> >
> > I eliminate the need to have a file on my file system.
> >
> > Thank you.  oss++ * mailing_lists++
>
> If you want, it's actually possible to take this even further and
> remove rewrite completely.
>
> <Location /etexts/id/>
>    SetHandler perl-script
>    PerlHandler Apache2::Alex::SemanticWeb
> </Location>
>
> Then alter your handler's code to parse $r->uri and extract
> everything after $r->location.  (or you can use $r->path_info, if the
> /etexts/id/ actually exists in your document root).  That'll give you
> the same thing that rewrite is currently stuffing into your id
> argument.

Never use path_info unless you are very sure it is what you want. 
Path_info is made for CGI scripts where $r->filename points to the file 
containing the script.

The usage of path_info leads to action at a distance problems. Assume 
you have an empty directory DOCROOT/etexts/id and path_info s what you 
want. Later an administrator adds a file or subdirectory to that 
directory or removes the id directory. Suddenly path_info has changed 
but the handler and all libraries it uses are still the same.

substr($r->uri, length $r->location) is almost always what you need.

Torsten

-- 
Need professional mod_perl support?
Just hire me: torsten.foertsch@gmx.net

Re: rewriterule, location, and perlhandler

Posted by Adam Prime <ad...@utoronto.ca>.
Eric Lease Morgan wrote:
> 
> On Jul 22, 2009, at 12:05 AM, Adam Prime wrote:
> 
> By first changing my Location directive to the following:
> 
>  <Location /sandbox/semantic-web/>
>    SetHandler perl-script
>    PerlHandler Apache2::Alex::SemanticWeb
>  </Location>
> 
> And then changing my RewriteRule to this:
> 
>   RewriteRule ^/etexts/id/(.*) /sandbox/semantic-web/?id=$1 [passthrough]
> 
> I eliminate the need to have a file on my file system.
> 
> Thank you.  oss++ * mailing_lists++
> 

If you want, it's actually possible to take this even further and remove 
rewrite completely.

<Location /etexts/id/>
   SetHandler perl-script
   PerlHandler Apache2::Alex::SemanticWeb
</Location>

Then alter your handler's code to parse $r->uri and extract everything 
after $r->location.  (or you can use $r->path_info, if the /etexts/id/ 
actually exists in your document root).  That'll give you the same thing 
that rewrite is currently stuffing into your id argument.

Adam




Re: rewriterule, location, and perlhandler

Posted by Eric Lease Morgan <er...@infomotions.com>.
On Jul 22, 2009, at 12:05 AM, Adam Prime wrote:

>>>>  <Location /sandbox/semantic-web.cgi>
>>>>    SetHandler perl-script
>>>>    PerlHandler Apache2::Alex::SemanticWeb
>>>>  </Location>
>>>>
>>>> What am I doing wrong? Does an actual file need to exist in order  
>>>> for
>>>> mod_perl to find it?
>>>
>>> No.
>>
>> I didn't think so, but what sort of configuration do I need to do  
>> so my
>> mod_perl packages get executed without the existence of a file?
>
> You need to use Handlers.  See this link for a really simple example  
> of
> a ResponseHandler, and how to configure it.
>
> http://perl.apache.org/docs/2.0/user/intro/start_fast.html#Handler_Modules


By first changing my Location directive to the following:

  <Location /sandbox/semantic-web/>
    SetHandler perl-script
    PerlHandler Apache2::Alex::SemanticWeb
  </Location>

And then changing my RewriteRule to this:

   RewriteRule ^/etexts/id/(.*) /sandbox/semantic-web/?id=$1  
[passthrough]

I eliminate the need to have a file on my file system.

Thank you.  oss++ * mailing_lists++

-- 
Eric Lease Morgan


Re: rewriterule, location, and perlhandler

Posted by Adam Prime <ad...@utoronto.ca>.
Eric Lease Morgan wrote:
> 
> On Jul 21, 2009, at 9:45 PM, Nick Wellnhofer wrote:
> 
>>> What am I doing wrong? Does an actual file need to exist in order for
>>> mod_perl to find it?
>>
>> No.
> 
> 
> I didn't think so, but what sort of configuration do I need to do so my
> mod_perl packages get executed without the existence of a file?
> 

You need to use Handlers.  See this link for a really simple example of
a ResponseHandler, and how to configure it.

http://perl.apache.org/docs/2.0/user/intro/start_fast.html#Handler_Modules

Adam

Re: rewriterule, location, and perlhandler

Posted by Eric Lease Morgan <er...@infomotions.com>.
On Jul 21, 2009, at 9:45 PM, Nick Wellnhofer wrote:

>> What am I doing wrong? Does an actual file need to exist in order for
>> mod_perl to find it?
>
> No.


I didn't think so, but what sort of configuration do I need to do so  
my mod_perl packages get executed without the existence of a file?

-- 
Eric Morgan


Re: rewriterule, location, and perlhandler

Posted by Nick Wellnhofer <we...@aevum.de>.
Eric Lease Morgan wrote:
> What am I doing wrong? Does an actual file need to exist in order for
> mod_perl to find it?

No.

> How should I edit httpd.conf so I can: 1) rewrite
> GET requests, and 2) execute the result in a mod_perl module?

Try the mod_rewrite "passthrough" (PT) flag:

    RewriteRule ^/etexts/id/(.*) /sandbox/semantic-web.cgi?id=$1 [PT]

More info here:
http://modperlbook.org/html/12-8-mod_rewrite-Examples.html

Nick

Re: rewriterule, location, and perlhandler [resolved]

Posted by Eric Lease Morgan <er...@infomotions.com>.
On Jul 21, 2009, at 9:32 PM, Eric Lease Morgan wrote:

> How do I get Apache's RewriteRule, Location, and PerlHander to work  
> nicely together?...
>
> I now want to implement a RewriteRule -- a la a "cool" linked data  
> URL -- to redirect URLs with a specific shape to SemanticWeb.pm, and  
> I use the following:
>
>  RewriteRule ^/etexts/id/(.*) /sandbox/semantic-web.cgi?id=$1
>
> In other words, all request starting with /etexts/id should be  
> redirected (rewritten) to go to semantic-web.cgi. Unfortunately, all  
> requests go directly to the touched file and not to my Perl package;  
> the Location directive seems by-passed....


Resolved. Alas, I needed to add [passthrough] to my RewriteRule  
configuration:

   RewriteRule ^/etexts/id/(.*) /sandbox/semantic-web.cgi?id=$1  
[passthrough]

 From the mod_rewrite documentation:

   * 'passthrough|PT' (pass through to next handler)

   This flag forces the rewrite engine to set the uri field of the
   internal request_rec structure to the value of the filename
   field. This flag is just a hack to enable post-processing of the
   output of RewriteRule directives, using Alias, ScriptAlias,
   Redirect, and other directives from various URI-to-filename
   translators. For example, to rewrite /abc to /def using
   mod_rewrite, and then /def to /ghi using mod_alias:

     RewriteRule ^/abc(.*) /def$1 [PT]
     Alias /def /ghi

   If you omit the PT flag, mod_rewrite will rewrite uri=/abc/... to
   filename=/def/... as a full API-compliant URI-to-filename
   translator should do. Then mod_alias will try to do a
   URI-to-filename transition, which will fail. Note: You must use
   this flag if you want to mix directives from different modules
   which allow URL-to-filename translators. The typical example is
   the use of mod_alias and mod_rewrite.

   http://httpd.apache.org/docs/2.0/mod/mod_rewrite.html


I sincerely apologize for wasting people's time and bandwidth.

-- 
Eric Lease Morgan