如何在Mojolicious应用程序的单元测试中伪造客户端IP地址?

sim*_*que 12 perl unit-testing mojolicious

在我的Mojolicious应用程序中,我需要使用客户端的IP地址($c->tx->remote_address)来限制服务的速率.这很好用.

我现在正在尝试为此功能构建单元测试,但我在测试中伪造客户端的IP时遇到问题.

首先我认为local_address在Mojo :: UserAgent可能会做我想要的,但这是用户代理在本地绑定应用程序的地方,并且更改它会破坏所有内容,因为它无法再找到应用程序.

然后我尝试使用Sub :: Override来替换remote_addressMojo :: Transaction,但是当我这样做时$t->post_ok,它已经应用于客户端,它会尝试向不存在的IP发送请求,因为客户端的远程地址是服务器的地址,我遇到了一个永远不会成功的等待阻塞请求,因为它想要的服务器不存在.

您可以使用以下MCVE来尝试.预期的结果是测试通过.

use strict;
use warnings;
use Test::More;
use Test::Mojo;
use Mojolicious::Lite;

get '/foo' => sub { my $c = shift; $c->render( text => $c->tx->remote_address ) };

my $t = Test::Mojo->new;
$t->get_ok('/foo')->content_like(qr/\Q127.0.0.1/);

# TODO change client IP address to 10.1.1.1
# in a way that the /foo route sees it
$t->get_ok('/foo')->content_like(qr/\Q10.1.1.1/);

done_testing;
Run Code Online (Sandbox Code Playgroud)

我知道如何使用Catalyst和Dancer(或其他基于Test :: Plack的系统)执行此操作,但这些方法在此处不起作用.

sim*_*que 11

Mojolicious的作者在IRC上指出要查看Mojo dist中的单元测试以获得X-Forwarded-For头部实现,所以我做到了.

我们需要设置$ENV{MOJO_REVERSE_PROXY}在单元测试真值并重新启动服务器,然后发送一个X-Forwarded-For新的IP地址,事情就只是工作头.

use strict;
use warnings;
use Test::More;
use Test::Mojo;
use Mojolicious::Lite;

get '/foo' => sub { my $c = shift; $c->render( text => $c->tx->remote_address ) };

my $t = Test::Mojo->new;
$t->get_ok('/foo')->content_like(qr/\Q127.0.0.1/);

{
    local $ENV{MOJO_REVERSE_PROXY} = 1;
    $t->ua->server->restart;
    $t->get_ok( '/foo' => { 'X-Forwarded-For' => '10.1.1.1' } )->content_like(qr/\Q10.1.1.1/);
}

done_testing;
Run Code Online (Sandbox Code Playgroud)

测试现在通过了.

ok 1 - GET /foo
ok 2 - content is similar
ok 3 - GET /foo
ok 4 - content is similar
1..4
Run Code Online (Sandbox Code Playgroud)