[cgiapp] cgi::application::dispatch under PSGI

Kurt Lidl kurt.lidl at cello.com
Fri Mar 2 16:20:41 EST 2012


On 2/28/2012 2:33 PM, Rhesa Rozendaal wrote:
> On 02/28/2012 05:45 PM, Kurt Lidl wrote:
>> Greetings.
>>
>> I've got a large application that is running under mod_perl, running on
>> Apache 2.2.22.
>> Everything is working OK there.  It uses CGI::Application::Dispatch as
>> its invocation
>> method.
> I'm using roughly the same stack, though I use starman in dev, and
> intend to do so in prod as well (behind an apache reverse proxy).
>
>> I became interested in making that application work under PSGI.  Since
>> that is
>> now supported natively by modern versions of CGI::Application, I figured
>> it shouldn't
>> be too hard to make this work.
> It's not hard, but I found out it takes jumping through some hoops.
>
>> I've got a dead-simple .psgi file:
>>
>> --- snip, snip ---
>> use lib ('..');
>>
>> use Data::Dump qw(dump ddx);
>> use CWS1::Dispatch;
>>
>> CWS1::Dispatch->as_psgi;
>> --- snip, snip ---
> Here's mine, using your class name as example:
>
> --- snip, snip ---
> use CWS1::Dispatch;
> use CGI::PSGI;
>
> my $cgiapp = sub {
>       my $env = shift;
>       CWS1::Dispatch->as_psgi(
>       args_to_new =>  {
>           QUERY     =>  CGI::PSGI->new($env),
>       })->($env);
> };
> --- snip, snip ---
>
> The key here is that I found I needed to make sure each request gets a
> fresh instance of a CGI::PSGI object.
This was part of the problem I was having.  Thanks for that tip.  I am 
now using
a .psgi file just like the one you constructed.
>> In my Dispatch.pm file, I have this:
> Mine is the same (in structure).
>
> There's nothing specific in my regular apps, and I do receive params
> from CA::Dispatch. So I think you'll get it working in your situation
> too, as long as you make sure you pass in a fresh CGI::PSGI object every
> time.
>
>
The trickier part to debug was this -- why I wasn't getting parameters 
passed into
my application.

As it turns out, the LocationMatch directive I had was the problem:

<LocationMatch "^/cws1/(?!static/).*$">
          SetHandler perl-script
          PerlHandler Plack::Handler::Apache2
          PerlSetVar psgi_app /path/to/websvc/CWS1/CWS1.psgi
          Order allow,deny
          Allow from all
</LocationMatch>

The Plack::Handler::Apache2 code whacks the PATH_INFO of the environment
after striping off the components of the original PATH_INFO that match the
regular expression in the LocationMatch.

Normally, you might have something like <LocationMatch "^/cws/foo">.

The problem with the regex I was using that it matched everything in the 
PATH_INFO,
so the Apache2 handler was changing PATH_INFO into just "/", rather than 
leaving
it as "/cws1".

I changed my LocationMatch directive to merely be: "^/cws1/(?!static/)" 
and that works
just fine now.

I think, in my reading about this, that this is still subtly wrong, and 
it really should be
"/+cws1/+(?!static/+)/". Because LocationMatch doesn't collapse multiple 
slash
characters together.  So /cws1//static would still be dispatched, 
whereas /cws1/static
would not.  (See the special "Note about / (slash)" section in the 
Apache core module
documentation on the "Location" header, for the gory details.)

-Kurt





More information about the cgiapp mailing list