Running CGI Scripts Under Catalyst

It is possible to run most CGI scripts under Catalyst using the modules Catalyst::Controller::WrapCGI and Catalyst::Controller::CGIBin.

Why would you want to do this?

Assuming you have a legacy CGI application, you may want to:

  • integrate and package a CGI script into your Catalyst application, so you can (for example) use the Catalyst Authentication framework.
  • have a Perl CGI script compiled on startup and cached, as with ModPerl::Registry, but in a FastCGI environment rather than with mod_perl under Apache.

port a simple mod_perl application to Catalyst.

An Example

Let's get the wwwboard application from the NMS project (http://nms-cgi.sourceforge.net/scripts.shtml) running under Catalyst.

We'll call the Catalyst application WWWBoard.

First, make a root/cgi-bin directory in your app, then copy the file wwwboard.pl there.

Put the files wwwboard.html and faq.html into root/static.

Edit the configuration block in wwwboard.pl to:

    $basedir =  WWWBoard->path_to('root/static');
    $baseurl = 'http://localhost:3000/';
    $cgi_url = 'http://localhost:3000/cgi-bin/wwwboard.pl';

Next, make a Controller for running your CGIs:

    package WWWBoard::Controller::Board;

    use strict;
    use warnings;
    use parent 'Catalyst::Controller::CGIBin';

    1;

Tell Static::Simple to not ignore .html files in WWWBoard.pm:

    __PACKAGE__->config(
        name => 'WWWBoard',
        static => {
            ignore_extensions => [ 'tt' ],
        },
    );

Rewire some URLs to the files the CGI will generate in Controller/Root.pm:

    __PACKAGE__->config->{namespace} = '';

    sub index : Path Args(0) {
        my ($self, $c) = @_;

        $c->serve_static_file($c->path_to('/root/static/wwwboard.html'));
    }

    sub board_html : Path('wwwboard.html') Args(0) {
        my ($self, $c) = @_;

        $c->serve_static_file($c->path_to('/root/static/wwwboard.html'));
    }

    sub faq_html : Path('faq.html') Args(0) {
        my ($self, $c) = @_;

        $c->serve_static_file($c->path_to('/root/static/faq.html'));
    }

    sub messages :Local Args {
        my ($self, $c, @args) = @_;

        $c->serve_static_file($c->path_to('/root/static/messages', @args));
    }

Start the server, and you will be taken to a functional message board.

Even non-Perl CGIs will work, but of course these will not be pre-compiled.

Porting mod_perl Apps

The CGI environment is a bit closer to mod_perl than the regular Catalyst Controller environment, e.g. you can print to STDOUT.

The first step would be to rewrite your handler sub to take $c instead of $r as a parameter, and replace the Apache request methods with the equivalent Catalyst framework methods.

Replacing things like Apache::Session with Catalyst::Plugin::Session is also fairly trivial.

Then your URL handler would look like:

    use parent 'Catalyst::Controller::WrapCGI';
    require My::ModPerl::Handler;

    sub my_handler : Local {
        my ($self, $c, @args) = @_;

        $self->cgi_to_response($c, sub {
            My::ModPerl::Handler::handler($c);
        });
    }

Other Examples

Justin Hunter (arcanez) has gotten the Movable Type blogging software running under Catalyst. It is available here: http://github.com/arcanez/mtcatalyst.

Hans Dieter Pearcey (confound) has gotten the Bugzilla bug-tracking project running under Catalyst. It is available here: http://opensourcery.com/blog/hans-dieter-pearcey/bugzilla-catalyst.

AUTHOR

Caelum: Rafael Kitover <rkitover@cpan.org>