TheChosenOne has asked for the wisdom of the Perl Monks concerning the following question:

I've got a CGI script that I want to convert to PSGI. This is the result:
use CGI::Emulate::PSGI; use strict; use warnings; use CGI qw(:cgi-lib :standard); use CGI::Carp qw(warningsToBrowser fatalsToBrowser); my $q = new CGI; my @keys = param(); my $state = ""; if(scalar @keys > 0){ $state = $keys[0]; } my $app = CGI::Emulate::PSGI->handler(sub { @keys = $q->param(); print $q->header; print "<center>"; print $q->h1('Some title'); print "</center>"; print $q->start_html(-title => 'Some title'); print $keys[0]; home(); sub home{ print "<center>"; print $q->h3('Pick an option.'); print $q->end_form; print "</center>"; print "<center>"; my $q0 = new CGI; print $q0->start_form( -name => 'some_button', -method => 'POST', -enctype => &CGI::URL_ENCODED, ); print $q0->submit( -name => 'click_me', -value => 'Do something', ); print $q0->end_form; print "</center>"; } print $q->end_form; });
After I click on 'Do something', I return to the same page (obviously), but it should print 'click_me'. This worked in CGI, but for some reason PSGI doesn't pass this variable. I can print other variables that are defined above. So my @keys = param(); doesn't seem to do a whole lot. Edit: Apparently PSGI uses %ENV, but I can't make it work with POST. It works with GET.

Edit: The solution is actually very easy. 'Your Mother' has the solution. I knew that you could compile your CGI scripts and emulate them. But if your run a perl server (like plackup), you get the next error: plackup: Variable "$variable" is not available at /location/of/script." The solution is to change the permissions of all global variables from 'my' to 'our'.

Replies are listed 'Best First'.
Re: Passing variables in PSGI
by Your Mother (Archbishop) on Sep 08, 2014 at 15:39 UTC

    You declare your CGI (well, one of them) outside your handler and your handler has a nested named sub. Nesting named subs typical doesn’t work the way you think. Instead of trying to untangle it I would just recycle your CGI script verbatim and change the psgi code to look like this (CGI::Compile and CGI::Emulate::PSGI).

    my $sub = CGI::Compile->compile("/path/to/YOUR-SCRIPT.cgi"); my $app = CGI::Emulate::PSGI->handler($sub);
Re: Passing variables in PSGI
by Anonymous Monk on Sep 09, 2014 at 00:26 UTC
    Remember the comments from Manually add parameters in perl cgi? especially Re: Manually add parameters in perl cgi ( no ReadParse no CGI->Vars?
    #!/usr/bin/perl -- ## ## ## ## perltidy -olq -csc -csci=3 -cscl="sub : BEGIN END " -otr -opr -ce +-nibc -i=4 -pt=0 "-nsak=*" ## perltidy -olq -csc -csci=10 -cscl="sub : BEGIN END if " -otr -opr +-ce -nibc -i=4 -pt=0 "-nsak=*" #!/usr/bin/perl -- use strict; use warnings; use CGI (); use CGI::Carp qw(warningsToBrowser fatalsToBrowser); Main( @ARGV ); exit( 0 ); sub Main { #~ return DebugCGI(); #~ return RootPage(); return ToPsgi(); } ## end sub Main sub ToPsgi { my $sub = CGI::Compile->compile( __FILE__ ); my $app = CGI::Emulate::PSGI->handler( $sub ); return $app; } ## end sub ToPsgi sub RootPage { my $q = CGI->new; print $q->header, RootTemplate( $q ); } ## end sub RootPage sub RootTemplate { my( $q ) = @_; my @keys = $q->param(); print $q->header; print "<center>"; print $q->h1( 'Some title' ); print "</center>"; print $q->start_html( -title => 'Some title' ); print $keys[0]; print SomePage(); print $q->end_form; } ## end sub RootTemplate sub SomePage { my $q = shift || CGI->new( {} ); my $ret = join "\n", "<center>", $q->h3( 'Pick an option.' ), $q->end_form, "</center>", "<center +>", $q->start_form( -name => 'some_button', -method => 'POST', -enctype => &CGI::URL_ENCODED, ), $q->submit( -name => 'click_me', -value => 'Do something', ), $q->end_form, "</center>", ; return $ret; } ## end sub SomePage sub DebugCGI { my $cgi = CGI->new; binmode STDOUT, ':encoding(UTF-8)'; $cgi->charset( 'UTF-8' ); print $cgi->header( -charset => 'UTF-8' ); print $cgi->start_html, $cgi->b( rand time, ' ', scalar gmtime ), '<table border="1" width="%100"><tr><td>', $cgi->Dump, '</td>', '<td><div style="white-space: pre-wrap; overflow: scroll;">', $cgi->escapeHTML( DD( $cgi ) ), '</div></td></tr></table>', CGI->new( \%ENV )->Dump, $cgi->end_html; } ## end sub DebugCGI sub DD { require Data::Dumper; return scalar Data::Dumper->new( \@_ )->Indent( 1 )->Useqq( 1 )->D +ump; } ## end sub DD
Re: Passing variables in PSGI
by sundialsvc4 (Abbot) on Sep 09, 2014 at 00:40 UTC