package Squatting::On::CGI; #use strict; #no strict 'refs'; #use warnings; use CGI; use CGI::Cookie; use HTTP::Response; # p for private my %p; $p{init_cc} = sub { my ($c, $q) = @_; my $cc = $c->clone; $cc->env = { %ENV }; $cc->cookies = $p{c}->($ENV{HTTP_COOKIE}); $cc->input = $p{i}->($q); $cc->headers = { 'Content-Type' => 'text/html' }; $cc->v = { }; $cc->status = 200; $cc; }; # \%input = i($q) # Extract CGI parameters from a CGI object $p{i} = sub { my $q = $_[0]; my %i = $q->Vars; +{ map { if ($i{$_} =~ /\0/) { $_ => [ split("\0", $i{$_}) ]; } else { $_ => $i{$_}; } } keys %i } }; # \%cookies = c($cookie_header) # Parse Cookie header(s). $p{c} = sub { +{ map { ref($_) ? $_->value : $_ } CGI::Cookie->parse($_[0]) }; }; sub cgi { my ($app, $q) = @_; $ENV{PATH_INFO} ||= '/'; $ENV{REQUEST_PATH} ||= do { my $script_name = $ENV{SCRIPT_NAME}; $script_name =~ s{/$}{}; $script_name . $ENV{PATH_INFO}; }; $ENV{REQUEST_URI} ||= do { ($ENV{QUERY_STRING}) ? "$ENV{REQUEST_PATH}?$ENV{QUERY_STRING}" : $ENV{REQUEST_PATH}; }; eval { my ($c, $args) = &{$app."::D"}($ENV{REQUEST_PATH}); my $cc = $p{init_cc}->($c, $q); my $content = $app->service($cc, @$args); my $response = HTTP::Response->new( $cc->status, undef, [ %{ $cc->{headers} } ], $content ); print "Status: " . $response->as_string; }; if ($@) { print $q->header(-status => 500); print "
$@
"; } } 1; =head1 NAME Squatting::On::CGI - if all else fails, you can still deploy on CGI =head1 SYNOPSIS Create an app.cgi to drive the Squatting app in a CGI environment. use App 'On::CGI'; my $q = CGI->new; App->init; App->relocate('/cgi-bin/app.cgi'); App->cgi($q); =head1 DESCRIPTION The purpose of this module is to allow Squatting apps to be used in a CGI environment. This is done by adding a C method to the Squatting app that knows how to "translate" between CGI and Squatting. To use this module, pass the string C<'On::CGI'> to the C statement that loads your Squatting app. =head1 API =head2 CGI -- The Lowest Common Demoninator =head3 App->cgi($q) Give the C method a CGI object, and it will send the apps output to STDOUT. =head1 SEE ALSO L =cut # Local Variables: *** # mode: cperl *** # indent-tabs-mode: nil *** # cperl-close-paren-offset: -2 *** # cperl-continued-statement-offset: 2 *** # cperl-indent-level: 2 *** # cperl-indent-parens-as-block: t *** # cperl-tab-always-indent: nil *** # End: *** # vim:tabstop=8 softtabstop=2 shiftwidth=2 shiftround expandtab