我的目标是:
$tx->req->to_string
重用程序如下所示:
use Mojo::Util qw/dumper/;
use Mojo::File qw/path/;
use Mojo::UserAgent;
use Mojo::Message::Request;
use Mojo::Transaction::HTTP;
my $req_string = path($ARGV[0])->slurp;
my $ua = Mojo::UserAgent->new;
my $tx = Mojo::Transaction::HTTP->new;
$tx->req->parse($req_string);
print dumper $tx->req; # seems to print a valid Mojo::Message::Request object
$tx = $ua->start($tx);
# this fails with Can't call method "server" on an undefined value at /home/me/perl5/perlbrew/perls/perl-5.30.2/lib/site_perl/5.30.2/Mojo/Server/Daemon.pm line 55.
print dumper $tx->res->body;
在第 16 行失败了
Can't call method "server" on an undefined value at /home/me/perl5/perlbrew/perls/perl-5.30.2/lib/site_perl/5.30.2/Mojo/Server/Daemon.pm line 55.
总的来说,这似乎失败了:
use Mojo::UserAgent;
my $ua = Mojo::UserAgent->new;
my $tx = Mojo::Transaction::HTTP->new;
# more transaction defining stuff
$tx = $ua->start($tx);
print $tx->res->body; # success!
my $txt = $tx->req->to_string;
$tx = Mojo::Transaction::HTTP->new;
$tx->req->parse($txt);
$tx = $ua->start($tx); # failure!
print $tx->res->body;
我做错了什么?
我不知道这是否是一个错误。这似乎解决了问题:
$tx = 'Mojo::Transaction::HTTP'->new;
$tx->req->parse($txt);
$tx->req->url->scheme($tx->req->url->base->scheme);
$tx->req->url->host($tx->req->url->base->host);
$tx = $ua->start($tx); # No more failures!
为什么这有帮助?
如果添加了 Carp::Always,你会看到错误来自 Mojo::UserAgent:
中的第 317 行 if (!$url->is_abs && (my $server = $self->server)) {
my $base = $loop == $self->ioloop ? $server->url : $server->nb_url; # <- LINE 317.
$url->scheme($base->scheme)->host($base->host)->port($base->port);
}
为什么 $url 不是绝对的?因为在 Mojo::URL 中,
is_abs
定义为
sub is_abs { !!shift->scheme }
如果我们检查来自请求的 url,它确实没有方案:
#! /usr/bin/perl
use warnings;
use strict;
use feature qw{ say };
use Mojo::Message::Request;
use Mojo::URL;
my $url1 = 'Mojo::URL'->new('http://example.com');
say $url1->to_string, ' ', $url1->is_abs ? 'abs' : '!abs'; # Is absolute.
my $txt = join "\r\n", 'GET / HTTP/1.1', 'Host: example.com', "", "";
my $url2 = 'Mojo::Message::Request'->new->parse($txt)->url;
say $url2->to_string, ' ', $url2->is_abs ? 'abs' : '!abs'; # Isn't absolute!
如果您Data::Dumper url:
,您可以看到差异:$VAR1 = bless( {
'query' => bless( {
'pairs' => [],
'charset' => 'UTF-8'
}, 'Mojo::Parameters' ),
'path' => bless( {
'parts' => [],
'leading_slash' => '',
'charset' => 'UTF-8',
'trailing_slash' => ''
}, 'Mojo::Path' ),
'scheme' => 'http',
'host' => 'example.com'
}, 'Mojo::URL' );
$VAR1 = bless( {
'path' => bless( {
'charset' => 'UTF-8',
'path' => '/'
}, 'Mojo::Path' ),
'query' => bless( {
'charset' => 'UTF-8',
'pairs' => []
}, 'Mojo::Parameters' ),
'base' => bless( {
'scheme' => 'http',
'host' => 'example.com'
}, 'Mojo::URL' )
}, 'Mojo::URL' );
这也是上面的 hack 解决问题的原因:它在第二个 URL 中设置了缺少的方案和主机。
现在让我们等待更精通 Mojo 的人向我们解释这一切。