如何使用 Mojo::UserAgent 从已解析的字符串创建请求

问题描述 投票:0回答:1

我的目标是:

  • 使用 Mojo::UserAgent 手动创建有效交易
  • 一旦成功,请使用
    $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;

我做错了什么?

perl mojolicious
1个回答
0
投票

我不知道这是否是一个错误。这似乎解决了问题:

    $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 的人向我们解释这一切。

© www.soinside.com 2019 - 2024. All rights reserved.