You are viewing a plain text version of this content. The canonical link for it is here.
Posted to modperl@perl.apache.org by Steve Hay <st...@uk.radan.com> on 2003/09/08 17:51:55 UTC
Help wanted with locations / configuration
Hi,
I'm having trouble deciding what the best plan is for the arrangement of
the components of a new project that I'm starting.
The project is going to be written as a series of mod_perl handlers -
one for the main "home page", and others for various sub-components.
Each handler is implemented by a separate module (all sub-classes of a
common base class). I don't want to have to configure a separate
Location for each sub-component.
It also needs to have access to various static resources (images,
stylesheets, JavaScript libraries etc.).
Thus, I want to have something like this:
/myproject [mp1]
/myproject/component1 [mp1]
/myproject/component2 [mp1]
...
/myproject/images [static]
/myproject/javascript [static]
/myproject/stylesheets [static]
The question is: What is the best way to configure this?
So far I've come up with two options:
OPTION 1. Specify a /myproject Location with "dispatcher" method as the
mod_perl handler; then specify a LocationMatch for the images,
javascript and stylesheets that overrides the /myproject Location:
<Location /myproject>
SetHandler perl-script
PerlHandler MyProject->dispatcher
</Location>
<LocationMatch "^/myproject/(images|javascript|stylesheets)">
SetHandler default-handler
</LocationMatch>
The "dispatcher" method there looks at the URI requested and either
returns DECLINED (or 404?) if it doesn't recognise it, or else loads the
appropriate MyProject sub-class and then runs the real content
generation routine in that (i.e. a routine like I would have specified
as the handler for that URI if I had configured a separate Location for
each component).
This seems to have a minor problem in practice -- if I request a
directory, rather than a file, in one of the "static" locations (e.g.
"/myproject/images" or "/myproject/images/") then the dispatcher method
gets called! The LocationMatch override only seems to work if I request
a file (e.g. "/myproject/images/piccy1.jpg"). Thus, I need to put some
extra code into the dispatcher to repeat the pattern match for the
"static" locations, and change the handler to the default-handler and
return DECLINED if it has received such a URI.
OPTION 2. Specify a /myproject Location with a PerlFixupHandler that
behaves very much like the dispatcher above, except that it actually
sets the handler to PerlHandler and assigns the appropriate callback
method (i.e. the content generation routine in the component sub-class)
when it spots a recognised component URI; otherwise it just returns
DECLINED, leaving the request to be handled by the default-handler:
<Location /myproject>
PerlFixupHandler MyProject->fixup
</Location>
(Am I correct in thinking that I don't need to specify "SetHandler:
perl-script" for a PerlFixupHandler? That's only for the main
PerlHandler response handler, isn't it?)
Does either of these options have any benefit over the other? Are there
other better ways to do it?
Thanks in advance,
- Steve
Re: Help wanted with locations / configuration
Posted by petersm <pe...@venzia.com>.
Steve Hay <st...@uk.radan.com> wrote
>
> Thanks for the idea, though. If I manage to overcome my
> inexplicable aversion to file extensions then it certainly looks
> like the simplest solution.
I understand the argument that it's better for the user to not know the
extension of the file they are running.... but, if it really bothers you then
you could do something like
<Location /myproject>
AddHandler perl-script .steve
</Location>
and then put a '.steve' extension onto your scripts and that way it's a little
more personalized... :)
Michael Peters
Venzia
Re: Help wanted with locations / configuration
Posted by Steve Hay <st...@uk.radan.com>.
petersm wrote:
>Steve Hay <st...@uk.radan.com> wrote
>
>
>><Location /myproject>
>> SetHandler perl-script
>> PerlHandler MyProject->dispatcher
>></Location>
>>
>><LocationMatch "^/myproject/(images|javascript|stylesheets)">
>> SetHandler default-handler
>></LocationMatch>
>>
>>
>
>Correct me if I'm wrong, but can't you just say> <Location /myproject>
>
> <Location /myproject>
> AddHandler perl-script .cgi
> PerlHandler MyProject->dispatcher
> </Location>
>
>using AddHandler instead of SetHandler. This will not override the default
>handler for things like images/stylesheets/static html. This way you don't
>need the <LocationMatch "^/myproject/(images|javascript|stylesheets)"> ... tags.
>
>
I prefer for reasons that I can't really explain to have the Perl
handler locations having no extension - e.g. things like
"/myproject/component1" rather than "/myproject/component1.cgi".
I can't see how to achieve that with an AddHandler. (And even if I did
get that working somehow, then the Perl handler would have to hand
control back to the Apache core when it receives a request for
"/myproject/images".)
Thanks for the idea, though. If I manage to overcome my inexplicable
aversion to file extensions then it certainly looks like the simplest
solution.
- Steve
Re: Help wanted with locations / configuration
Posted by petersm <pe...@venzia.com>.
Steve Hay <st...@uk.radan.com> wrote
> It also needs to have access to various static resources (images,
> stylesheets, JavaScript libraries etc.).
>
> Thus, I want to have something like this:
>
> /myproject [mp1]
> /myproject/component1 [mp1]
> /myproject/component2 [mp1]
> ...
> /myproject/images [static]
> /myproject/javascript [static]
> /myproject/stylesheets [static]
> <Location /myproject>
> SetHandler perl-script
> PerlHandler MyProject->dispatcher
> </Location>
>
> <LocationMatch "^/myproject/(images|javascript|stylesheets)">
> SetHandler default-handler
> </LocationMatch>
Correct me if I'm wrong, but can't you just say> <Location /myproject>
<Location /myproject>
AddHandler perl-script .cgi
PerlHandler MyProject->dispatcher
</Location>
using AddHandler instead of SetHandler. This will not override the default
handler for things like images/stylesheets/static html. This way you don't
need the <LocationMatch "^/myproject/(images|javascript|stylesheets)"> ... tags.
Michael Peters
Venzia
Re: Help wanted with locations / configuration
Posted by Xavier Noria <fx...@hashref.com>.
On Tuesday 09 September 2003 11:16, Steve Hay wrote:
> Those were actually my very frist ideas, but I decided that I prefer
> to have all the URL's to begin with /myproject. I don't necessarily
> require that URL to be related to the filesystem structure, but I
> just want all the URL's (dynamic and static) to begin the same.
I have achieved that using the configuration Perrin suggested. The prefix
(/myproject) is a parameter of the configuration of the application called
"apache_location_root", and the config script fills a mod_perl.conf.tt2
like this:
Alias [% apache_location_root %]/views [% prj_root %]/www/htdocs/views
Alias [% apache_location_root %]/images [% prj_root %]/www/htdocs/images
Alias [% apache_location_root %]/scripts [% prj_root %]/www/htdocs/scripts
Alias [% apache_location_root %]/styles [% prj_root %]/www/htdocs/styles
<Location [% apache_location_root %]>
# Nothing to do with the filesystem, just handlers available in @INC.
</Location>
In our case the motivation for that is that we don't know whether our
application will run in its own Apache server, so you can hard-code that
stuff, or will need to be added to an already functioning Apache.
-- fxn
Re: Help wanted with locations / configuration
Posted by Steve Hay <st...@uk.radan.com>.
Perrin Harkins wrote:
>On Mon, 2003-09-08 at 11:51, Steve Hay wrote:
>
>
>>Thus, I want to have something like this:
>>
>>/myproject [mp1]
>>/myproject/component1 [mp1]
>>/myproject/component2 [mp1]
>>...
>>/myproject/images [static]
>>/myproject/javascript [static]
>>/myproject/stylesheets [static]
>>
>>The question is: What is the best way to configure this?
>>
>>
>
>Others have already given good advice,
>
They have, indeed. Thanks, everyone!
>but I would add that your URLs
>and your filesystem don't need to be tied tightly together. You could
>just alias the static files to somewhere else:
>
>[snip]
>
>Alternatively, you could use a Location setting for your dispatcher that
>has nothing to do with your files:
>
>
Those were actually my very frist ideas, but I decided that I prefer to
have all the URL's to begin with /myproject. I don't necessarily
require that URL to be related to the filesystem structure, but I just
want all the URL's (dynamic and static) to begin the same.
- Steve
Re: Help wanted with locations / configuration
Posted by Perrin Harkins <pe...@elem.com>.
On Mon, 2003-09-08 at 11:51, Steve Hay wrote:
> Thus, I want to have something like this:
>
> /myproject [mp1]
> /myproject/component1 [mp1]
> /myproject/component2 [mp1]
> ...
> /myproject/images [static]
> /myproject/javascript [static]
> /myproject/stylesheets [static]
>
> The question is: What is the best way to configure this?
Others have already given good advice, but I would add that your URLs
and your filesystem don't need to be tied tightly together. You could
just alias the static files to somewhere else:
Alias /static/images /myproject/images
Then you can simply refer to them in URLs as /static/images/foo.jpg.
Alternatively, you could use a Location setting for your dispatcher that
has nothing to do with your files:
<Location /wild/and/crazy/path/for/handlers>
SetHandler perl-script
PerlHandler MyProject->dispatcher
</Location>
Then you can call /wild/and/crazy/path/for/handlers/component1 and it
will work as long as your dispatcher is smart enough to ignore the
beginning path. (Apache::Dispatch is.)
- Perrin
Re: Help wanted with locations / configuration
Posted by Thomas Klausner <do...@zsi.at>.
Hi!
On Tue, Sep 09, 2003 at 10:05:43AM +0100, Steve Hay wrote:
> ><Location /myproject/css>
> > SetHandler default
> ></Location>
> ><Location /myproject/img>
> > SetHandler default
> ></Location>
> >
> >This is working as expected, i.e. request for /css/foo.css or /img/bar.png
> >are not handled by Apache::Dispatch
> >
> >
> What about requests for /css or /img ? Are they handled by
> Apache::Dispatch? The problem I found with my LocationMatch override is
> that requests for files were caught, but requests for directories
> slipped through to the Perl handler.
Unfourtunatly, request for /css are handled by Apache::Dispatch. At least it
seems so, but I'm enterly sure if it's the actual request that's beeing
served, or an internal redirect (or some other funky Apache internal thing,
like ErrorDocument or index generation)
It does seem like a feature/problem of Apache. I tried various config
options (and modifications to Apache::Dispatch), but no matter what I did,
request for /img/ allways get passed to PerHandler instead of default
handler
Request for anything inside /img/ work as expected.
No, wait a minute...
If I request /foo/bar/ (another dir) than it doesn't work either.
I still do not know if this a bug in
Apache / mod_perl / Apache::Dispatch / YourHandler, and/or internal redirect.
Or if this is expected behaviour.
--
#!/usr/bin/perl http://domm.zsi.at
for(ref bless{},just'another'perl'hacker){s-:+-$"-g&&print$_.$/}
Re: Help wanted with locations / configuration
Posted by Steve Hay <st...@uk.radan.com>.
Steve Hay wrote:
> Thomas Klausner wrote:
>
>> Hi!
>>
>> On Mon, Sep 08, 2003 at 04:51:55PM +0100, Steve Hay wrote:
>>
>>
>>
>>> The project is going to be written as a series of mod_perl handlers
>>> - one for the main "home page", and others for various
>>> sub-components. Each handler is implemented by a separate module
>>> (all sub-classes of a common base class). I don't want to have to
>>> configure a separate Location for each sub-component.
>>>
>>
>>
>> You might want to take a look at Apache::Dispatch, which does exactly
>> this.
>>
> Will do! I've grabbed it off CPAN and will take a good look at it.
> It does indeed look like exactly what I'm after.
Does anybody have Apache::Dispatch working on Windows?
I'm trying to build it on Windows XP (MSVC++ 6) with Perl 5.8.0 / Apache
1.3.27 / mod_perl 1.28, but I get these errors:
[...]
link -out:blib\arch\auto\Apache\Dispatch\Dispatch.dll -dll
-nologo -node
faultlib -release -libpath:"C:\perl5\lib\CORE" -machine:x86
Dispatch.obj C:\
perl5\lib\CORE\perl58.lib libeay32.lib oldnames.lib kernel32.lib
user32.lib gdi
32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib
oleaut32.li
b netapi32.lib uuid.lib wsock32.lib mpr.lib winmm.lib version.lib
odbc32.lib o
dbccp32.lib msvcrt.lib -def:Dispatch.def
Creating library blib\arch\auto\Apache\Dispatch\Dispatch.lib and
object blib\
arch\auto\Apache\Dispatch\Dispatch.exp
Dispatch.obj : error LNK2001: unresolved external symbol
_perl_perl_merge_dir_co
nfig
Dispatch.obj : error LNK2001: unresolved external symbol
_perl_cmd_perl_TAKE1
Dispatch.obj : error LNK2001: unresolved external symbol
__imp__ap_register_clea
nup@16
Dispatch.obj : error LNK2001: unresolved external symbol
_perl_perl_cmd_cleanup
Dispatch.obj : error LNK2001: unresolved external symbol
__imp__ap_null_cleanup
Dispatch.obj : error LNK2001: unresolved external symbol __imp__ap_palloc@8
Dispatch.obj : error LNK2001: unresolved external symbol _perl_clear_symtab
Dispatch.obj : error LNK2001: unresolved external symbol
__imp__ap_remove_module
@4
Dispatch.obj : error LNK2001: unresolved external symbol
__imp__ap_find_linked_m
odule@4
Dispatch.obj : error LNK2001: unresolved external symbol
_perl_get_startup_pool
Dispatch.obj : error LNK2001: unresolved external symbol
__imp__ap_add_module@4
blib\arch\auto\Apache\Dispatch\Dispatch.dll : fatal error LNK1120: 11
unresolved
externals
NMAKE : fatal error U1077: 'link' : return code '0x460'
Stop.
Any ideas?
- Steve
Re: Help wanted with locations / configuration
Posted by Steve Hay <st...@uk.radan.com>.
Thomas Klausner wrote:
>Hi!
>
>On Mon, Sep 08, 2003 at 04:51:55PM +0100, Steve Hay wrote:
>
>
>
>>The project is going to be written as a series of mod_perl handlers -
>>one for the main "home page", and others for various sub-components.
>>Each handler is implemented by a separate module (all sub-classes of a
>>common base class). I don't want to have to configure a separate
>>Location for each sub-component.
>>
>>
>
>You might want to take a look at Apache::Dispatch, which does exactly this.
>
Will do! I've grabbed it off CPAN and will take a good look at it. It
does indeed look like exactly what I'm after.
>I'm using something like this with Apache::Dispatch
>
>PerlModule Apache::Dispatch
>DispatchUpperCase On # this is /not/ in Apache::Dispatch,
> # only in my patched version
>DispatchPrefix Oe1
>DispatchExtras Error
>
><Location /myproject>
> SetHandler perl-script
> PerlHandler Apache::Dispatch
></Location>
>
><Location /myproject/css>
> SetHandler default
></Location>
><Location /myproject/img>
> SetHandler default
></Location>
>
>This is working as expected, i.e. request for /css/foo.css or /img/bar.png
>are not handled by Apache::Dispatch
>
>
What about requests for /css or /img ? Are they handled by
Apache::Dispatch? The problem I found with my LocationMatch override is
that requests for files were caught, but requests for directories
slipped through to the Perl handler.
- Steve
Re: Help wanted with locations / configuration
Posted by Thomas Klausner <do...@zsi.at>.
Hi!
On Mon, Sep 08, 2003 at 04:51:55PM +0100, Steve Hay wrote:
> The project is going to be written as a series of mod_perl handlers -
> one for the main "home page", and others for various sub-components.
> Each handler is implemented by a separate module (all sub-classes of a
> common base class). I don't want to have to configure a separate
> Location for each sub-component.
You might want to take a look at Apache::Dispatch, which does exactly this.
> <Location /myproject>
> SetHandler perl-script
> PerlHandler MyProject->dispatcher
> </Location>
>
> <LocationMatch "^/myproject/(images|javascript|stylesheets)">
> SetHandler default-handler
> </LocationMatch>
I'm using something like this with Apache::Dispatch
PerlModule Apache::Dispatch
DispatchUpperCase On # this is /not/ in Apache::Dispatch,
# only in my patched version
DispatchPrefix Oe1
DispatchExtras Error
<Location /myproject>
SetHandler perl-script
PerlHandler Apache::Dispatch
</Location>
<Location /myproject/css>
SetHandler default
</Location>
<Location /myproject/img>
SetHandler default
</Location>
This is working as expected, i.e. request for /css/foo.css or /img/bar.png
are not handled by Apache::Dispatch
--
#!/usr/bin/perl http://domm.zsi.at
for(ref bless{},just'another'perl'hacker){s-:+-$"-g&&print$_.$/}
Re: Help wanted with locations / configuration
Posted by Marc Slagle <ma...@whapps.com>.
On Tue, 2003-09-09 at 05:00, Steve Hay wrote:
> As in a PerlTransHandler, yes?
Yup.
> Is there a performance penalty with this? You're using Perl code to
> inspect the URI, and then handing control back to the Apache core if it
> is a static file. I wanted to avoid requests for static files wasting
> time by going to a Perl handler only to be returned to the Apache core
> to serve the file, hence my LocationMatch override that catches requests
> for static files.
Static File:
Devel::Timer Report -- Total time: 0.0006 secs
Interval Time Percent
----------------------------------------------
00 -> 01 0.0003 48.49% INIT -> Entering translation handler
01 -> 02 0.0002 36.91% Entering translation handler -> Checking to
see if we are asking for a static file
02 -> 03 0.0001 14.60% Checking to see if we are asking for a static
file -> This is a request for a static file, telling apache where it is
Request we want to pass on to our handler:
Devel::Timer Report -- Total time: 0.0005 secs
Interval Time Percent
----------------------------------------------
01 -> 02 0.0002 40.90% Entering translation handler -> Checking to
see if we are asking for a static file
00 -> 01 0.0001 31.48% INIT -> Entering translation handler
02 -> 03 0.0001 27.62% Checking to see if we are asking for a static
file -> This is not a request for a static file, returning DENIED
We decided to do it this way because we are also doing some other things
in the translation handler that I didn't pass along in the snippet.
Since we were already putting a translation handler in place to do our
trickery there, it seemed to make the most sense to us to add the code
to handle static requests there. By no means am I suggesting that this
is the "best" way, but we're pretty happy with it.
Marc Slagle
Re: Help wanted with locations / configuration
Posted by Steve Hay <st...@uk.radan.com>.
Marc Slagle wrote:
>On Mon, 2003-09-08 at 11:51, Steve Hay wrote:
>
>
>>It also needs to have access to various static resources (images,
>>stylesheets, JavaScript libraries etc.).
>>
>>Thus, I want to have something like this:
>>
>>/myproject [mp1]
>>/myproject/component1 [mp1]
>>/myproject/component2 [mp1]
>>...
>>/myproject/images [static]
>>/myproject/javascript [static]
>>/myproject/stylesheets [static]
>>
>>
>
>You might want to look at having a translation handler.
>
As in a PerlTransHandler, yes?
>
>We're doing something similar to this, where images and javascripts live
>under the same directory structure as the handler is managing. Instead
>of trying to configure this via that httpd.conf file, we chose to have a
>translation handler look at the incoming uri and determine whether the
>request is for a static file or for the code.
>
Is there a performance penalty with this? You're using Perl code to
inspect the URI, and then handing control back to the Apache core if it
is a static file. I wanted to avoid requests for static files wasting
time by going to a Perl handler only to be returned to the Apache core
to serve the file, hence my LocationMatch override that catches requests
for static files.
Thanks for the code snippet, though - it looks pretty good to me aside
from that concern.
- Steve
Re: Help wanted with locations / configuration
Posted by Marc Slagle <ma...@whapps.com>.
On Mon, 2003-09-08 at 11:51, Steve Hay wrote:
>
> It also needs to have access to various static resources (images,
> stylesheets, JavaScript libraries etc.).
>
> Thus, I want to have something like this:
>
> /myproject [mp1]
> /myproject/component1 [mp1]
> /myproject/component2 [mp1]
> ...
> /myproject/images [static]
> /myproject/javascript [static]
> /myproject/stylesheets [static]
You might want to look at having a translation handler.
We're doing something similar to this, where images and javascripts live
under the same directory structure as the handler is managing. Instead
of trying to configure this via that httpd.conf file, we chose to have a
translation handler look at the incoming uri and determine whether the
request is for a static file or for the code.
Inside of our transhandler we're doing this:
sub handler
{
my $r=shift;
my $uri=$r->uri;
my $Tmplpath="/our/static/files/rootdir/";
if (($uri !~ /jpg$/) && ($uri !~ /css$/) && ($uri !~ /js$/))
{
$r->notes('host' => "$Host");
$r->notes('olduri' => "$uri");
$r->uri("/");
return DECLINED;
}
else
{
my $File=$Tmplpath . $uri;
$r->filename("$File");
return OK;
}
}
If a request is made for anything ending in .jpg, .js or .css, we tell
apache where to find the file by appending the uri (/images/the.jpg for
example) to a path. The handler then returns OK, which tells apache not
to try to figure out where the file lives on its own, and returns the
file to the browser.
Any other request is passed to the handler, along with a field in
notes() that shows what we were asking for in the first place. Our
request handler uses this to dispatch the request to the correct object
needed to fulfill the request. (Our handler is configured at /, so we
override the uri passed from the browser to /).
Any other types you want can be added to this, I just threw the ones
that seemed relevant to you. I hope this helps.
Marc Slagle
Whapps LLC