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

天大地大妈咪最大 提交于 2020-01-01 08:13:30

问题


In my Mojolicious app I need to use the client's IP address ($c->tx->remote_address) for rate limiting of a service. This works well.

I am now trying to build a unit test for this feature, but I am having trouble faking the client's IP in my tests.

First I thought that local_address in Mojo::UserAgent might do what I want, but that's where the user agent binds the application locally, and changing it breaks everything because it cannot find the app any more.

I then tried using Sub::Override to replace the remote_address in Mojo::Transaction, but that already applies to the client when I do $t->post_ok, it tries sending a request to the IP that doesn't exist because the remote address on the client side is the server's address, and I am stuck with a waiting blocking request that will never succeed because the server it wants does not exist.

You can use the following MCVE to try around. The expected result is for the tests to pass.

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;

I know how to do this with Catalyst and Dancer (or other Test::Plack based systems), but those approaches don't work here.


回答1:


The author of Mojolicious pointed out on IRC to look at the unit tests in the Mojo dist for the X-Forwarded-For header implementation, so I did.

We need to set the $ENV{MOJO_REVERSE_PROXY} to a true value in the unit test and restart the server, then send an X-Forwarded-For header with the new IP address and things will just work.

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;

The tests now pass.

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


来源:https://stackoverflow.com/questions/46960660/how-do-i-fake-the-client-ip-address-in-a-unit-test-for-a-mojolicious-app

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!