Why does my system call to another CGI script work on the command line but not when run as a CGI program?

对着背影说爱祢 提交于 2019-12-04 04:55:06

问题


I have a scriptA.cgi which calls scriptB.cgi.

scriptB.cgi requires a param.

I have tried both inside scriptA.cgi I have tried:

`perl -l scriptB.cgi foo="toast is good" `;

as well as

@args = ("perl", "-l", "scriptB.cgi", "foo=\"toast is good\"");
system(@args);

When I call scriptA.cgi from the command line it works as expected. However when I call scriptA.cgi through the browser scriptB.cgi is executed but it fails to read the incoming param and prints foo as empty.

Is there a less ugly way to call one cgi from another and pass in params?

scriptB does not have to be a cgi, if it's easier to do this with a straight .pl and args, I'm happy to do that too... but the arg has to be a quoted string with spaces.

All thoughts welcome.


回答1:


If there is common functionality shared between many scripts, put it in a module

Modules may seem intimidating, but they are really very simple.

File SMSTools.pm:

package SMSTools;
use strict;
use warnings;
use Exporter qw(import);

# Name subs (and variables, but don't do that) to export to calling code:
our @EXPORT_OK = qw( send_sms_message );

our @EXPORT = @EXPORT_OK;  
# Generally you should export nothing by default.
# However, for simple cases where there is only one key function
# provided by a module, I believe it is reasonable to export it by default.


sub send_sms_message {
    my $phone_number = shift;
    my $message      = shift;

    # Do stuff.

    return; # Return true on successful send.
}

# Various supporting subroutines as needed.

1;  # Any true value.

Now, to use your module in foo.cgi:

use strict;
use warnings;
use CGI;

use SMSTools;

my $q = CGI->new;

my $number = $q->param_fetch( 'number');
my $message = $q->param_fetch( 'msg');

print 
    $q->header,
    $q->start_html,
    (    send_sms_message($number, $message) 
         ? $q->h1("Sent SMS Message") 
         : $q->h1("Message Failed")
    ),
    q->end_html; 

See perlmod, and the docs for Exporter for more information.




回答2:


I suspect that the CGI environment is getting in your way. Are you using CGI.pm?

When you run your CGI script from the command line, you probably haven't set any of the CGI environment variables, such as QUERY_STRING. The CGI script starts up, notices its missing those environment variables, and thinks it must have been run from the command line. If it thinks it has been run from the command line, it looks in other places, such as @ARGV, for the data. That would be my first guess.

There are various things that might be going on in the CGI program case. Mostly likely, scriptB.cgi is using the same environment set-up for scriptA.cgi and it doesn't have the parameters or data it expects. Since the CGI environment is set up and there isa QUERY_STRING variable, it never thinks to look in @ARGV.

However, you have many options depending on what you want to do (and this goes a bit beyond your situation):

  • If you only need scriptB.cgi to support other scripts (i.e. browsers should never call it directly), make it a library or a module. You should always try to do this. Make every script at least a modulino.

  • If scriptB.cgi is a standalone CGI script and should stay that way, make a sub request in scriptA.cgi so all the normal CGI stuff gets set up through the server.

  • If you don't want to make a subrequest, localize %ENV, which child processes will share, and fake the CGI environment yourself. That's a bit of work, but not too hard.




回答3:


One option is also to use a hidden field to pass parameters between CGI scripts. As the name implies, these fields are not visible to the user but can be used to pass parameters just as any other field.




回答4:


See "Decoding Form Output" here:

http://www.cgi101.com/class/ch4/text.html

(Her post.cgi script was invaluable to me in diagnosing this issue.)

And another thing to be aware of for those of you using CGI.pm--it uses multipart/form-data for its default encoding type, which "is suitable for forms that ... are intended for transferring binary data." Interestingly, changing the encoding type to the other option made everything work as one would expect:

enctype=>"application/x-www-form-urlencoded"

(Tested with Windows XP, Perl 5.10, CGI.pm 3.43, and Apache 2)




回答5:


Here's a snippet from some code I wrote that has a *.cgi script calling a Perl script:

$note = "toast is good";
$cmd = "addAccTrans.pl $priAcc $date $priGrp \"$note\" $amt";<br />
open($f, "perl $cmd|");<br />
while(<$f>) { print "$_\n" };<br />
close($f);<br />

The CGI script captures the output of the Perl script and prints it out again.




回答6:


A:

#!/usr/bin/perl
print "Content-type: text/html\n\n";
{
    local $foo = "toas is bad";
    do 'b.cgi';
}

B:

#!/usr/bin/perl
print "$foo";


来源:https://stackoverflow.com/questions/2002664/why-does-my-system-call-to-another-cgi-script-work-on-the-command-line-but-not-w

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!