是否可以在没有其他HTTP请求的情况下将POST参数发送到CGI脚本? [英] Is it possible to send POST parameters to a CGI script without another HTTP request?

查看:119
本文介绍了是否可以在没有其他HTTP请求的情况下将POST参数发送到CGI脚本?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试从另一个Perl模块在当前环境中运行CGI脚本.使用标准系统调用GET请求,所有方法都能正常工作. POST也很好,直到参数列表过长,然后它们就会被切断.

I'm attempting to run a CGI script in the current environment from another Perl module. All works well using standard systems calls for GET requests. POST is fine too, until the parameter list gets too long, then they get cut off.

有人遇到过这个问题,或者对尝试此问题的其他方法有任何建议吗?

Has anyone ran in to this problem, or have any suggestions for other ways to attempt this?

为清楚起见,以下内容进行了一些简化.还有更多错误检查等.

对于 GET请求不带参数的POST请求,我执行以下操作:

For GET requests and POST requests w/o parameters, I do the following:

# $query is a CGI object.
my $perl = $^X;
my $cgi  = $cgi_script_location; # /path/file.cgi
system {$perl} $cgi;

  • 参数通过 QUERY_STRING环境变量.
  • STDOUT被呼叫捕获 脚本,所以无论CGI脚本如何 打印效果正常.
  • 这部分有用.
    • Parameters are passed through the QUERY_STRING environment variable.
    • STDOUT is captured by the calling script so whatever the CGI script prints behaves as normal.
    • This part works.
    • 对于带有参数的 POST请求,以下方法有效,但似乎限制了我的可用查询长度:

      For POST requests with parameters the following works, but seemingly limits my available query length:

      # $query is a CGI object.
      my $perl = $^X;
      my $cgi  = $cgi_script_location; # /path/file.cgi
      
      # Gather parameters into a URL-escaped string suitable 
      # to pass to a CGI script ran from the command line.
      # Null characters are handled properly.
      # e.g., param1=This%20is%20a%20string&param2=42&... etc.
      # This works.
      my $param_string = $self->get_current_param_string();
      
      # Various ways to do this, but system() doesn't pass any 
      # parameters (different question).
      # Using qx// and printing the return value works as well.
      open(my $cgi_pipe, "|$perl $cgi");
      print {$cgi_pipe} $param_string;
      close($cgi_pipe);
      

      • 此方法适用于简短的参数列表,但是如果整个命令接近于1000个字符,则会缩短参数列表.这就是为什么我尝试将参数保存到文件中的原因.避免外壳的限制.
      • 如果我从执行的CGI脚本中转储参数列表,则会得到类似以下的内容:
      • param1=blah
        ... a bunch of other parameters ...
        paramN=whatever
        p <-- cut off after 'p'. There are more parameters.

        param1=blah
        ... a bunch of other parameters ...
        paramN=whatever
        p <-- cut off after 'p'. There are more parameters.

        我所做的其他事情无济于事

        • 遵循 CGI故障排除指南
        • 使用CGI-> save()将参数保存到文件中,然后将该文件传递给CGI脚本.使用此方法只能读取第一个参数.

        $> perl index.cgi < temp-param-file

        • 将$ param_string保存到文件中,将该文件传递到CGI脚本中,就像上面一样.与通过命令行传递命令具有相同的限制;仍然被切断.
        • 确保$CGI::POST_MAX很高(为-1).
        • 确保CGI的命令行处理正常. (:未设置no_debug)
        • 从命令行使用相同的参数运行CGI.这行得通.
        • Saved $param_string to a file, passing that file to the CGI script just like above. Same limitations as passing the commands through the command line; still gets cut off.
        • Made sure $CGI::POST_MAX is acceptably high (it's -1).
        • Made sure the CGI's command-line processing was working. (:no_debug is not set)
        • Ran the CGI from the command line with the same parameters. This works.

        • 很显然,这似乎是Perl用于执行命令的shell的字符限制,但是并不能通过将参数传递到文件来解决.

        推荐答案

        事实证明,该问题实际上与原始参数和我拼凑在一起的参数字符串之间的Content-Length差异有关.我没有意识到CGI模块正在使用原始标头中的该值作为读取多少输入的限制(很有意义!).显然,我正在执行的额外转义操作是添加一些字符.

        Turns out that the problem is actually related to the difference in Content-Length between the original parameters and the parameter string I cobbled together. I didn't realize that the CGI module was using this value from the original headers as the limit to how much input to read (makes sense!). Apparently the extra escaping I was doing was adding some characters.

        我的解决方案的窍门是简单地将要传递的参数字符串拼凑在一起,然后修改CGI模块将检查以确定其内容长度等于的环境变量.

        My solution's trick is simply to piece together the parameter string I'll be passing and modify the environment variable the CGI module will check to determine the content length to be equal to the .

        这是最终的工作代码:

        use CGI::Util qw(escape);
        
        my $params;
        
        foreach my $param (sort $query->param) {
         my $escaped_param  = escape($param);
        
         foreach my $value ($query->param($param)) {
          $params .= "$escaped_param=" . escape("$value") . "&";
         }
        }
        
        foreach (keys %{$query->{'.fieldnames'}}) {
         $params .= ".cgifields=" . escape("$_") . "&";
        }
        
        # This is the trick.
        $ENV{'CONTENT_LENGTH'} = length($params);
        
        open(my $cgi_pipe, "| $perl $cgi_script") || die("Cannot fork CGI: $!");
        local $SIG{PIPE} = sub { warn "spooler pipe broke" };
        
        print {$cgi_pipe} $params;
        
        warn("param chars: " . length($params));
        
        close($cgi_pipe) || warn "Error: CGI exited with value $?";
        

        感谢所有帮助!

        这篇关于是否可以在没有其他HTTP请求的情况下将POST参数发送到CGI脚本?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆