CGIBin/WrapCGI under Apache2, but alongside ModPerl::Registry

79 views
Skip to first unread message

Tim Retout

unread,
Dec 1, 2012, 6:05:14 PM12/1/12
to psgi-...@googlegroups.com
Hi,

Co-incidentally to the other thread about Apache1 and $ENV{MOD_PERL}, I have been looking at running CGI scripts under Apache2.  I want to use Plack for only one location block, alongside other CGI scripts that are currently still run under ModPerl::Registry.

CGI.pm checks $ENV{MOD_PERL} at compile time, and sets $CGI::MOD_PERL = 2.  It then uses this value at runtime to determine how to print out headers, for example.  My initial problem was that $q->redirect statements in CGI scripts were not working under Plack::App::CGIBin - this can be fixed by deleting $ENV{MOD_PERL} before CGI is loaded, which Plack::Handler::Apache2 attempts to do (but whether it works seems to depend on the order that things are run at Apache startup time).

However, because I want to use ModPerl::Registry alongside Plack for now, I would like $ENV{MOD_PERL} to stay set at compile time.  I need $CGI::MOD_PERL = 0 at request time, and only under Plack.  This is unfortunate, because Catalyst, CGI::Cookie etc. will all have their own magic internal variables to set.

So to solve my immediate problem, I expect I will write some middleware like this:

package Plack::Middleware::MessWithCGI;
use parent qw( Plack::Middleware );

sub call {
    my($self, $env) = @_;

    local $CGI::MOD_PERL = 0;

    my $res = $self->app->($env);
    return $res;
}

1;

I need a better name for it.

I cannot see a good place to put a bug fix in for Plack - the obvious places are either Plack::Handler::Apache2 or Plack::App::WrapCGI, but either way this is quite ugly mod_perl/CGI-specific messing with internals.

For reference, my Apache2 config is quite close to the example in the Plack::Handler::Apache2 docs:

<Location /test>
SetHandler perl-script
PerlResponseHandler Plack::Handler::Apache2
PerlSetVar psgi_app /home/tim/src/perl/test.psgi
</Location>

And test.psgi is close to the example in the Plack::App::CGIBin docs:

use Plack::App::CGIBin;
use Plack::Builder;

my $app = Plack::App::CGIBin->new(root => "/home/tim/src/perl/cgi-bin")->to_app;
builder {
    mount "/cgi-bin" => $app;
};

And I have an index.cgi that just prints a redirect:

#!/usr/bin/perl

use strict;
use warnings;

use CGI;

my $q = CGI->new();

print $q->redirect('/test/cgi-bin/foo.cgi');
exit;

Ævar Arnfjörð Bjarmason

unread,
Dec 4, 2012, 6:07:27 AM12/4/12
to psgi-...@googlegroups.com
On Sun, Dec 2, 2012 at 12:05 AM, Tim Retout <t...@retout.co.uk> wrote:
> Co-incidentally to the other thread about Apache1 and $ENV{MOD_PERL}, I have
> been looking at running CGI scripts under Apache2. I want to use Plack for
> only one location block, alongside other CGI scripts that are currently
> still run under ModPerl::Registry.
>
> CGI.pm checks $ENV{MOD_PERL} at compile time, and sets $CGI::MOD_PERL = 2.
> It then uses this value at runtime to determine how to print out headers,
> for example. My initial problem was that $q->redirect statements in CGI
> scripts were not working under Plack::App::CGIBin - this can be fixed by
> deleting $ENV{MOD_PERL} before CGI is loaded, which Plack::Handler::Apache2
> attempts to do (but whether it works seems to depend on the order that
> things are run at Apache startup time).
>
> However, because I want to use ModPerl::Registry alongside Plack for now, I
> would like $ENV{MOD_PERL} to stay set at compile time. I need
> $CGI::MOD_PERL = 0 at request time, and only under Plack.

You can do this with the middleware like you suggest, but this
approach is really fragile. It's only going to work for things that
check $ENV{MOD_PERL} at runtime, but there's some things that will
check it at compile time (maybe not the specific code you're dealing
with though) and the only way to sort that out is to:

* Run two Perl interpreters, one where you compile things with
MOD_PERL=1 and one without.

* Start adding some more unholy evil hacks that overwrite some
symbols in other packages depending on whether you want to serve
things under MOD_PERL or not (ew!)

I haven't checked but doesn't Apache support launching two mod_perl
interpreters? That would be a much cleaner solution to this at the
expense of some more memory use.
Reply all
Reply to author
Forward
0 new messages