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

Hello Monks,

I've been reading this place for a little while, and now I have my first question, working on some bigger-than-usual project using Perl/mod_perl.

So at first, I was using CGI. Then, I decided to use HTML::Template for all my HTML generation needs, thus obsoleting the CGI.pm HTML related functions. Reading some posts here at PM, I then replaced CGI with CGI::Simple (the transition was easy as the latter is syntax compliant with CGI, and the project was still early). Doing some testings, I realised a script stopped working: it was supposed to get form data through POST, validate that data, and display an error message, provided some happened (followed by the form to reenter the data). Basic stuff, really.

Problem: the script wasn't getting the data as expected anymore. Trying to pinpoint the source of the problem, I wrote the following post_test.pl script:

#!/usr/bin/perl use strict; use warnings; use CGI::Simple; my $cgi = new CGI::Simple; my @params = $cgi->param(); print <<HEAD; Content-Type: text/html; charset=iso-8859-1 <html><head><title>CGI::Simple POST Test</title></head> <body> HEAD print($cgi->param($_) . "<br />") for (@params); # nothing printed if +@params is empty print $cgi->Dump; # for debugging purpose print <<FORM; <form action="post_test.pl" method="POST"> <p>Foo: <input type="text" name="foo" size="30" maxlength="255" va +lue="" /></p> <p>Bar: <input type="text" name="bar" size="30" maxlength="255" va +lue="" /></p> <p><input type="submit" name="submit" value="Test" /></p> </form> </body> </html> FORM

At first, nothing was available through $cgi->param(). Reading the docs, I added the $cgi->Dump and got my first clue:

$VAR1 = bless( { '.globals' => { # skipped }, '.cgi_error' => '500 Bad read on POST! wanted 31, got + 0', '.mod_perl' => 1 }, 'CGI::Simple' );

Replacing every occurence of CGI::Simple with CGI made the problem go away, of course. Further investigations led me to Ovid's CGI Course. The second lesson was particularly interesting:

If, for some reason, you need to debug the information being sent via a POST with a form "enctype" of "multipart/form-data", you can use the following script, which is what I used to produce the output above. It doesn't use CGI.pm as I need to read from STDIN directly, which is not possible if CGI.pm is used.
#!c:/perl/bin/perl.exe -wT use strict; my $buffer; read (STDIN, $buffer, $ENV{'CONTENT_LENGTH'}); print "Content-type: text/plain\n\n"; print $buffer;

Unfortunately, that code didn't provide anything on my machine, whichever "enctype" I tried on that simple form. So, if any Monk among you has any other idea as to what I should try and do to find out about the origin of that problem, I will be forever grateful.

The setup:
Mac OS X 10.3.7 running Perl 5.8.1, mod_perl 1.26 and Apache 1.3.33.
Latest version of CGI and CGI::Simple, no forced install.

Thanks in advance.

Replies are listed 'Best First'.
Re: CGI::Simple POST data trouble
by CountZero (Bishop) on Jan 11, 2005 at 14:58 UTC
    I had a similar problem. The scripts work with CGI both for GET as for POST requests. With CGI::Simple only the GET requests seem to work, POST did not work at all and no obvious reason was found.

    Being strapped for time, I did not investigate further but converted all POST requests to GET requests.

    Silly work-around really, but as nobody complained, ...

    CountZero

    "If you have four groups working on a compiler, you'll get a 4-pass compiler." - Conway's Law

      I will definitely move back to CGI if I can't find a solution to this. I will probably take a look at the code of both modules first, just to make sure it's not the same. There has to be a few differences here and there for such a different behaviour in the same conditions.

      Who knows, maybe we just tackled one of those late-coming bug.

      And thanks for your answer, now I know I'm not alone out there. :)

Re: CGI::Simple POST data trouble
by BUU (Prior) on Jan 11, 2005 at 19:00 UTC
    A) Are you using mod_perl or not?
    B) The error message from CGI::Simple seems pretty explicit to me. The content-length was 31 but it couldn't read any data from STDIN. This is probably because you can only read data *once* from STDIN, so if anything has read the data from STDIN first, CGI::Simple won't then also be able to read the data.

    GET type requests don't work like this, as reading the appropate %ENV variable doesn't reset anything. So check to make sure nothing is reading the STDIN before you do -- you might consider scripts started by mod_perl related directives?

    C) If you are using mod_perl, I think you want Apache::Request or something similar.
      A) Are you using mod_perl or not?

      Yes. I've been reading the CGI::Simple docs carefully, and you probably know what it says about working alongside mod_perl:

      This module uses Selfloader and the __DATA__ token to ensure that only code that is used gets complied. This optimises performance but means that it will not work under mod_perl in its default configuration. To configure it to run under mod perl you would need to remove two lines from the module.
      use Selfloader; .... __DATA__

      Those two lines are commented in the source code of the module I'm using, so I guess that's enough. As an added bonus, here are the Apache config file and mod_perl startup file I'm using.

      B) The error message from CGI::Simple seems pretty explicit to me. The content-length was 31 but it couldn't read any data from STDIN. This is probably because you can only read data *once* from STDIN, so if anything has read the data from STDIN first, CGI::Simple won't then also be able to read the data.

      OK, makes sense

      GET type requests don't work like this, as reading the appropate %ENV variable doesn't reset anything. So check to make sure nothing is reading the STDIN before you do -- you might consider scripts started by mod_perl related directives?

      As far as I can tell, I have none, except that mod_perl_startup.pl I pasted up there.

      C) If you are using mod_perl, I think you want Apache::Request or something similar.

      OK, will take a look at that and give it a try. Thanks for the help.

      I'm running under mod_perl and I'm quite sure nothing is reading STDIN before my script as the POST requests under CGI.pm run OK, but don't run under CGI::Simple.

      CountZero

      "If you have four groups working on a compiler, you'll get a 4-pass compiler." - Conway's Law