gpt4 book ai didi

Perl:通过 mojolicious 的异步 http 代理

转载 作者:行者123 更新时间:2023-12-01 05:10:54 25 4
gpt4 key购买 nike

我做了一个简单的 http 代理,它工作正常,但速度不快,因为在函数 handle_request 中,我使用了

my $tx = $ua->start( Mojo::Transaction::HTTP->new(req=>$request) );

做请求,它是阻塞的。

我尝试使用这样的回调:

$ua->start( Mojo::Transaction::HTTP->new(req=>$request) )=>sub{ ... }

让它成为非阻塞的,然后,犯了一个错误:

'error' => { 'message' => 'Premature connection close'}

我想那是因为函数 handle_request 立即返回,它不等待回调完成。如果我使用信号量等待回调,那就意味着它再次阻塞。

#!/usr/bin/perl
use strict;
use warnings;
use utf8;
use Mojo::IOLoop::Server;
use Mojo::UserAgent;
use Mojo::Message::Response;
use Mojo::Message::Request;
use Mojo::Transaction::HTTP;
use Data::Dumper;

binmode STDOUT, ":encoding(UTF-8)";

my %buffer;

Mojo::IOLoop->server( {port => 3128} => sub {
my ($loop, $stream, $client) = @_;

$stream->on(
read => sub {
my ($stream, $chunk) = @_;

my $buffer = $buffer{$client}{read_buffer} .= $chunk;

if ($buffer =~ /^GET\s+|POST\s+|HEAD\s+(.*)\r\n\r\n$/i) {
$buffer{$client}{read_buffer} = '';
&handle_request($client,$stream,$buffer);
}

elsif ($buffer =~ /^CONNECT\s+(.*)\r\n\r\n$/i) {
$buffer{$client}{read_buffer} = '';
&handle_connect($stream,$buffer);
}

elsif($buffer{$client}{connection})
{
$buffer{$client}{read_buffer} = '';
Mojo::IOLoop->stream($buffer{$client}{connection})->write($chunk);
}

if(length($buffer)>= 20 *1024 * 1024) {
delete $buffer{$client};
Mojo::IOLoop->remove($client);
return;
}
});
});

sub handle_request{

my($client,$stream,$chunk) = @_;

my $request = Mojo::Message::Request->new;
$request = $request->parse($chunk);

my $ua = Mojo::UserAgent->new;
my $tx = $ua->start( Mojo::Transaction::HTTP->new(req=>$request) );

$stream->write( $tx->res->to_string );
}

sub handle_connect{
my ($stream, $chunk) = @_;
my $request = Mojo::Message::Request->new;
my $ua = Mojo::UserAgent->new;

$request = $request->parse($chunk);

print Dumper($request);
}

Mojo::IOLoop->start;

希望得到一些建议。

最佳答案

你有两个问题:

  1. 当您的代码具有阻塞风格时,您尝试调用 $ua->start 的非阻塞变体。函数 handle_request 必须有回调作为参数。如果您有回调链,那么实现它的最佳方法是使用 Mojo::IOLoop::Delay
  2. 当您在子 handle_request 中以非阻塞方式创建变量 $ua 时,您的变量将被垃圾收集器销毁,因为首先执行子 handle_request 的退出并销毁 $ua ,因为它是局部变量,然后从 $ua 得到答案。所以你会得到 Premature connection close。您需要将 $ua 的实例保存在别处以防止此类错误。

更新
write http/https 代理的错误变体,它只能通过 CONNECT 方法工作,并且有错误,第一条 http 消息不完整。

更新
我添加了另一个 http/https 代理示例,它正确读取第一条 http 消息并且不仅通过 CONNECT 方法工作。

更新
哦,Mojo 的作者写道 example https代理

关于Perl:通过 mojolicious 的异步 http 代理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34328152/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com