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

13

在我的 Mojolicious 应用中,我需要使用客户端的 IP 地址 ($c->tx->remote_address) 对服务进行速率限制。这样可以很好地工作。

现在我正在尝试为此功能构建单元测试,但是在测试中伪造客户端的 IP 地址时遇到了麻烦。

起初我认为在 Mojo::UserAgent 中的 local_address 可能可以做我想要的事情,但那里的用户代理将本地应用程序绑定在一起,改变它会破坏一切,因为它无法再找到应用程序了。

然后我尝试使用 Sub::Override 来替换 Mojo::Transaction 中的 remote_address,但当我执行 $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;

我知道如何在 Catalyst 和 Dancer(或其他基于 Test::Plack 的系统)中完成这个任务,但这些方法在这里不适用。
1个回答

13
作者在IRC上指出,在Mojo dist中查看X-Forwarded-For头实现的单元测试,所以我这样做了
我们需要在单元测试中将$ENV{MOJO_REVERSE_PROXY}设置为true,并重新启动服务器,然后发送一个带有新IP地址的X-Forwarded-For头,一切都会正常工作。
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;

测试现在通过了。

ok 1 - GET /foo
ok 2 - content is similar
ok 3 - GET /foo
ok 4 - content is similar
1..4

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接