在Perl中发送HTTP流请求

时间:2018-09-28 18:07:18

标签: perl lwp-useragent

我想使用HTTP流协议发送xml请求。其中传输编码为“分块”。目前,我正在使用LWP :: UserAgent发送xml事务。

my $userAgent = LWP::UserAgent->new;
my $starttime = time();
my $response = $userAgent->request(POST $url,
Content_Type => 'application/xml',
Transfer_Encoding => 'Chunked',
Content => $xml);


print "Response".Dumper($response);

但是我正在获取http状态代码411 Length Required。这表示“客户端错误响应代码表示服务器拒绝接受没有定义的请求”

在分块发送请求时如何处理?

2 个答案:

答案 0 :(得分:1)

LWP :: UserAgent的API并非旨在发送流,但是能够以最少的黑客攻击来发送。

use strict;
use warnings qw( all );

use HTTP::Request::Common qw( POST );
use LWP::UserAgent        qw( );

my $ua = LWP::UserAgent->new();

# Don't provide any content.
my $request = POST('http://stackoverflow.org/junk',
   Content_Type => 'application/xml',
);

# POST() insists on adding a Content-Length header.
# We need to remove it to get a chunked request.
$request->headers->remove_header('Content-Length');

# Here's where we provide the stream generator.
my $buffer = 'abc\n';
$request->content(sub {
   return undef if !length($buffer);                # Return undef when done.
   return substr($buffer, 0, length($buffer), '');  # Return a chunk of data otherwise.
});

my $response = $ua->request($request);
print($response->status_line);

使用代理(提琴手),我们可以看到确实确实发送了分块的请求:

Screenshot of proxy showing a chunked request was used


如果您已经像给出的示例中那样方便地使用了整个文档,那么使用分块请求毫无意义。取而代之的是,假设要在生成外部输出时上载某些外部工具的输出。为此,您可以使用以下代码:

open(my $pipe, '-|:raw', 'some_tool');
$request->content(sub {
   my $rv = sysread($pipe, my $buf, 64*1024);
   die $! if !defined($rv);
   return undef if !$rv;
   return $buf;
});

答案 1 :(得分:0)

  

但是我正在获取http状态码411所需长度。

即使在HTTP / 1.1中进行了标准化(但在HTTP / 1.0中未进行标准化),但并非所有服务器都能理解具有分段有效负载的请求。例如,自版本1.3.9(2012)起,nginx仅在请求内支持分块,请参见Is there a way to avoid nginx 411 Content-Length required errors?。如果服务器无法理解带有分块编码的请求,那么您就无法从客户端执行任何操作,也就是说,您根本无法使用分块传输编码。如果您可以控制服务器,请确保服务器确实支持它。

我也从来没有经验丰富的浏览器发送这样的请求,可能是因为它们不能保证服务器将支持这样的请求。我只看到移动应用程序在服务器和应用程序由同一方管理的情况下使用,因此可以保证对分块请求的支持。