【问题标题】:How can I get the entire request body with CGI.pm?如何使用 CGI.pm 获取整个请求正文?
【发布时间】:2021-08-21 20:09:09
【问题描述】:

我正在尝试编写一个 Perl CGI 脚本来处理 XML-RPC 请求,其中 XML 文档作为 HTTP POST 请求的主体发送。

CGI.pm 模块在从 HTTP 请求中提取命名参数方面做得很好,但我不知道如何让它给我整个 HTTP 请求正文(即 XML-RPC 请求中的 XML 文档我正在处理)。

如果不是 CGI.pm,是否有另一个模块能够从请求中解析出这些信息?我宁愿不必从环境变量中“手动”提取这些信息。感谢您的帮助。

【问题讨论】:

    标签: perl cgi


    【解决方案1】:

    您可以使用特殊参数名称 POSTDATA 获取原始 POST 数据。

    my $q = CGI->new;
    my $xml = $q->param( 'POSTDATA' );
    

    或者,您可以直接读取 STDIN 而不是使用 CGI.pm,但是您会失去 CGI.pm 所做的所有其他有用的东西。

    POSTDATA 技巧记录在优秀的 CGI.pm 文档here 中。

    【讨论】:

    • 确保您的 POST 请求的内容类型不是application/x-www-form-urlencodedmultipart/form-data,否则POSTDATA 将为空。像text/html 这样的其他任何东西都可以。编辑 - 哦,下面提到了 2 个答案...
    【解决方案2】:

    是的,可以使用 POSTDATA,但只有在请求 Content-Type 未设置为“multipart/form-data”时才有效。

    如果设置为“multipart/form-data”,CGI.pm 会自己处理内容,POSTDATA 不会被初始化。

    因此,其他选项包括$cgi->query_string 和/或$cgi->Dump

    $cgi->query_string 以 GET 格式 (param=value&...) 返回 POST 的内容,并且似乎没有办法简单地获取 POST STDIN 的内容,因为它们是由客户端传入的.

    因此,要获取 POST 请求的标准输入的实际内容,如果您可以选择修改 CGI.pm,您可以在第 620 行附近进行修改以将 @lines 的内容保存在变量中的某个位置,例如:

    $self->{standard_input} = join '', @lines;
    

    然后通过$cgi->{standard_input}访问。

    【讨论】:

      【解决方案3】:

      要处理所有情况,包括 Content-Typemultipart/form-data 的情况,请读取(并放回)原始数据,before CGI 会这样做。

      use strict;
      use warnings;
      
      use IO::Handle;
      use IO::Scalar;
      
      STDIN->blocking(1); # ensure to read everything
      my $cgi_raw = '';
      
      { 
        local $/; 
        $cgi_raw = <STDIN>;
        my $s;
        tie  *STDIN, 'IO::Scalar', \$s;
        print STDIN $cgi_raw;
        tied(*STDIN)->setpos(0);
      }
      
      use CGI qw /:standard/;
      ...
      

      【讨论】:

        猜你喜欢
        • 2019-01-07
        • 2010-12-16
        • 2015-08-10
        • 2021-03-07
        • 2019-11-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多