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

How do I fake the client IP address in a unit test for a Mojolicious app?

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

我现在正在尝试为此功能构建单元测试,但我在测试中无法伪造客户端的 IP。

首先我认为 local_address in Mojo::UserAgent 可能会做我想做的事,但那是用户代理在本地绑定应用程序的地方,更改它会破坏一切,因为它无法再找到该应用程序。

然后我尝试使用 Sub::Override to replace the remote_address in Mojo::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;

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

Mojolicious 的作者在 IRC 上指出要查看 X-Forwarded-For header 实现的 Mojo 分区中的单元测试,so I did.

我们需要在单元测试中将 $ENV{MOJO_REVERSE_PROXY} 设置为真值并重新启动服务器,然后使用新 IP 地址发送 X-Forwarded-For header工作。

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