http://qs321.pair.com?node_id=989703

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

Hi Monks,

I am developing a server-driven web application; the structure is the the typical one: A user enters data into a form, and after submission of the form, a CGI script on the server processes the form data. The webserver is Apache 2.x; the CGI script is written in Perl and uses the CGI module to extract the form data. This is working so far.

Let's call the CGI script described above ScriptA.pl.

Now, there is a second CGI script (ScriptB.pl). ScriptB.pl serves two purposes:

1) Like ScriptA.pl, it is called directly from the user's browser and processes form data (it also uses CGI.pm for doing that).

2) Under certain circumstances, it will be called by ScriptA.pl (using "system", "exec" or one of their friends), i.e. there is the following "call chain": User's browser with form ---> ScriptA.pl (via CGI) ---> ScriptB.pl.

I have the following problem: If ScriptB.pl is called from ScriptA.pl, ScriptB.pl must have access to all form data which originally is sent from the user's browser to ScriptA.pl, i.e. the form data must be passed somehow from ScriptA.pl to ScriptB.pl. I have no clue if there is a reasonable way to do that. So far, the following (idiotic) solutions have come to my mind:

- ScriptA.pl might transform the form data into command line parameters which are passed to ScriptB.pl when calling it. This has two serious disadvantages: I surely would have to write code which encodes the form data for the command line (all character sequences which might be treated specially by the shell would have to be transformed), and the form data might be very long, even longer than the maximum length which is allowed for a command line.

- ScriptA.pl might write the form data to a temporary file which is then read by ScriptB.pl. This is very costly (isn't it?), and ScriptB.pl still would have to be told the name of the temporary file.

What do you think about that problem?

Thank you very much,

Nocturnus

  • Comment on How to pass form data from a CGI script to its child process?

Replies are listed 'Best First'.
Re: How to pass form data from a CGI script to its child process?
by derby (Abbot) on Aug 25, 2012 at 12:58 UTC

    If you wrote modulinos instead of scripts or *better* used a framework like CGI::Application or Dancer or Mojolicious, you could get away with keeping everything in one process. While I *love* the unix way and pipelining, I don't think it's a good approach for *most* web programming tasks.

    -derby

      Thank you very much for your reply.

      Indeed, I did not know about modulinos. This technique is very interesting. It seems that it resembles the way I have done it now (see above).

      Regarding the frameworks: I admit that I don't like them very much because most of them are not flexible enough for what I want to do, or the learning curve is very steep. Every time I tried a framework or read the documentation of a framework, I have come to the conclusion that it would take more time to learn the tricks to break its limitations than the framework would save, or that the framework's philosophy was not mine.

      To make a long story short: Frameworks are not appropriate for me. I am very happy with putting my well-tested methods in several modules and use these modules from my applications.

      By the way, the same applies for the template systems. I have written my own template system which might not be appropriate for the mass market, but is very simple and just does what I want, thereby keeping maximum flexibility (i.e. I can write pure perl code without any restrictions in my HTML pages).

      Since your answer contains some very interesting hints, I have voted it up, although I have chose another solution.

      Regards,

      Nocturnus

Re: How to pass form data from a CGI script to its child process?
by Anonymous Monk on Aug 25, 2012 at 09:13 UTC

    I surely would have to write code which encodes the form data for the command line (all character sequences which might be treated specially by the shell would have to be transformed), and the form data might be very long, even longer than the maximum length which is allowed for a command line.

    You could use CGI

    SAVING THE STATE OF THE SCRIPT TO A FILE: $query->save(\*FILEHANDLE)
    and reading it
    my $q = CGI->new(\*IN);
    so when you use the list form of system, system $^X, 'scriptB.pl', 'some/file/something';

      Thank you very much for your reply.

      I just did not know that the CGI module is able to do that. In the past, I have used the CGI module heavily and thought that I would know the most important things about it, but this obviously was an error.

      I have tested your proposition, and it works great. But now, there was the problem how to tell script B.pl from where it should read the parameters (HTTP form data or file / STDIN). That was easy to solve, though:

      A.pl will call B.pl with an additional command line parameter. If B.pl finds this command line parameter when called, it knows that it has been called from another script and that it should read STDIN for the CGI data; otherwise, it knows that it has been called directly from the user's browser and that it should read the CGI data from the HTTP data.

      Thanks again,

      Nocturnus

Re: How to pass form data from a CGI script to its child process?
by aaron_baugher (Curate) on Aug 25, 2012 at 10:12 UTC

    There's another option: you could use a module like LWP::UserAgent in ScriptA.pl to talk to ScriptB.pl through its URL. That way you can pass the parameters just as a browser would pass them, and ScriptB.pl doesn't have to be changed at all. ScriptA.pl just has to take the output of ScriptB.pl and do whatever you had in mind for it.

    Aaron B.
    Available for small or large Perl jobs; see my home node.

      Thank you very much for your reply.

      Your solution has the advantage that script B.pl even could be on another server than script A.pl. But in this case, I don't need this feature, so the disadvantage of being "expensive" in networking terms outweighs the advantage.

      Therefore, I have chosen another solution (see above). Nevertheless, I have voted up your proposition because it surely will work and has an additional interesting feature.

      Regards,

      Nocturnus

Re: How to pass form data from a CGI script to its child process?
by cheekuperl (Monk) on Aug 25, 2012 at 09:49 UTC
    Would you like to use redirect from CGI to pass parameters from Script A to script B?
    In either case (that is B.pl being called from A.pl or B.pl being called/redirected to from users browser directly), B.pl shall read from CGI object.

      Thank you very much for your reply.

      Although I have chosen another solution (see above), I have voted your proposition up since I think that it could do what I asked for (I did not test, though).

      I didn't chose your solution because I generally don't like redirects very much (they sometimes seem to cause problems with search engines and other sorts of problems), and that they seem to be "expensive" in network terms.

      Nevertheless, thank you very much again for a solution that quite probably will work.

      Regards,

      Nocturnus