如何使用 CGI.pm 获取整个请求正文?

Posted

技术标签:

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

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

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

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

【问题讨论】:

【参考方案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/;
...

【讨论】:

以上是关于如何使用 CGI.pm 获取整个请求正文?的主要内容,如果未能解决你的问题,请参考以下文章

如何查看perl cgi.pm的版本

如何使用 Jersey 获取完整的 REST 请求正文?

WebClient - 如何获取请求正文?

如何在改造请求的正文中发布原始的整个 JSON?

Postman:如何在请求正文中使用环境变量

如何使用 C# 在 POST 请求中发送 json 请求正文数据