Mojo::Test to follow redirect?

122 views
Skip to first unread message

iaw4

unread,
May 27, 2017, 10:42:34 PM5/27/17
to Mojolicious

Dear M Users:  I am trying to have my tests follow my redirects.  The following snippet

my $t = Test::Mojo->new;
## $t->ua->max_redirects(100);
$t
->get_ok('http://localhost:3000/')->status_is(200);


produces 

ok 1 - GET http://localhost:3000/
not ok 2 - 200 OK
#   Failed test '200 OK'
#   at SylSpace.t line 10.
#          got: '302'
#     expected: '200'
1..2


which is what I want.  Uncomment the max_redirects, and instead of following, it dies on the get_ok

# Can't connect: nodename nor servname provided, or not known
not ok 1 - GET http://localhost:3000/
#   Failed test 'GET http://localhost:3000/'
#   at SylSpace.t line 10.
not ok 2 - 200 OK
#   Failed test '200 OK'
#   at SylSpace.t line 10.
#          got: undef
#     expected: '200'
1..2
# Looks like you failed 2 tests of 2.


I verified by hand on my chrome browser that it does end up in a good spot.  so how do I request a get, follow the redirect, perhaps test which url I am arriving on, and then test the result?

advice appreciated.

regards,

/iaw

Heiko Jansen

unread,
May 28, 2017, 10:10:32 AM5/28/17
to Mojolicious
According to the example at https://metacpan.org/pod/Test::Mojo#ua I´d say you´re doing it right.

I wonder, however, how uncommenting that line of code can lead to this error message:
"Can't connect: nodename nor servname provided, or not known"

- which is apparently not part of Mojolicious itself; cf. https://grep.metacpan.org/search?q=nodename+nor+servname&qd=&qft=

Hmmm, where does the redirect URL point to? Sure that it´s "localhost"?

- heiko

iaw4

unread,
May 28, 2017, 1:34:11 PM5/28/17
to Mojolicious

my app redirects to http://auth.localhost:3000/index , and from there to '/auth/authenticator' , which is where it stays---all of which are under the full control of the app itself.  (different users get different vanity domains.) . so, here is my stripped example:

#!/usr/bin/env perl
use Mojolicious::Lite;

my $s = sub {
 
my $c= shift;
 
( ($c->req->url->to_abs->host()) =~ /auth/) and return $c->redirect_to('/auth/index');
  $c
->redirect_to('http://auth.localhost:3000/index');
};

get "/index" => $s;
get "/" => $s;
get "/auth/index" => sub {
 
my $c= shift;
 
return $c->render( text => 'we have arrived in /auth/index' );
};

app
->start();


and

#!/usr/bin/env perl
use Test::More;
use Test::Mojo;

my $SylSpace= 'http://localhost:3000';


my $t = Test::Mojo->new;

$t
->ua->max_redirects(100);
$t
->get_ok($SylSpace.'/')->status_is(200); # ->content_like( qr{abc});

done_testing
();


and the output is
# Connection refused

not ok 1 - GET http://localhost:3000/
#   Failed test 'GET http://localhost:3000/'
#   at redirect.t line 9.

not ok 2 - 200 OK
#   Failed test '200 OK'
#   at redirect.t line 9.

#          got: undef
#     expected: '200'
1..2
# Looks like you failed 2 tests of 2.


My browser follows without problems.  I am guessing the Mojo Test daemon does not...

regards,

/iaw

Heiko Jansen

unread,
May 28, 2017, 2:12:14 PM5/28/17
to Mojolicious
Am Sonntag, 28. Mai 2017 19:34:11 UTC+2 schrieb iaw4:

my app redirects to http://auth.localhost:3000/index ,

Well, on my OpenSUSE box neither the "host" nor the "nslookup" (or "dig") commands return an IP address for "auth.localhost" (they do, of course, for "localhost"), so I´d say that explains the "Can't connect: nodename nor servname provided, or not known" error message in your initial post.

The new demo code shows a different error:

and the output is
# Connection refused
 
 AFAIK, you should _not_ provide a hostname and port as parameter to get_ok().
So I'd say a corrected test file should look like this:

use Test::More;
use Test::Mojo;
 
use FindBin;
require "$FindBin::Bin/../myapp.pl";
 
my $t = Test::Mojo->new;
 
$t
->ua->max_redirects(100);

$t
->get_ok('/')->status_is(200); # ->content_like( qr{abc});
 
done_testing
();

If I test this with your server code (running "perl myapp.pl test -v t/t.pl") I once again get the "Can't connect: nodename nor servname provided, or not known" error message.

My browser follows without problems.  I am guessing the Mojo Test daemon does not...

I´d say that the Chrome browser you use shows some non-standard behavior here since I believe that localhost isn't a proper domain that could take subdomains. 
But I cannot provide an authoritative source for that right now.
Try using a different browser like Firefox for a start.

- Heiko

iaw4

unread,
May 28, 2017, 7:25:13 PM5/28/17
to Mojolicious

thanks, heiko.  my site relies heavily on proper handling many host subdomains.    for example, my auth subdomain handles OAuth intereactions with google, which are subdomain specific.  and then each of my users has their own vanity subdomain, but they nicely share session information.  once logged into one subdomain, they can go to another.  so, for my case, the usual testing just within sites (get_ok('/')) is insufficient.  I really do need to work with full http:// and URLs to obtain the subdomain and make different decisions based on it.  I guess my app is unusual :-(.

localhost as a testname for websites was IMHO never a great choice as the solo definition.  localhost.test would have been a better (or additional) choice.  localhost.test should keep the testing to remain on 127.0.0.1, and just work the same way any other domain name works---subdomains and everything.  grrr.  alas, we live with what we have.

indeed, browsers treat subdomains on localhost differently.  chrome handles subdomains on localhost, but the M useragent and firefox and safari do not.

so here is one solution, although this one does not work in chrome:  Add 'localhost.test' and 'auth.localhost.test' at the end of 127.0.0.1 localhost in /etc/hosts and `# morbo -v appname -l http//localhost.test:3000`.  now, http://localhost.test:3000/ works just fine with safari, firefox, and the Mojolicious test agent (but not chrome).

in the end, this was not a Mojolicious bug, but a web bug.

thanks for the help, heiko.

regards,

/iaw

Heiko Jansen

unread,
May 29, 2017, 4:56:17 AM5/29/17
to Mojolicious
Am Montag, 29. Mai 2017 01:25:13 UTC+2 schrieb iaw4:
 
so here is one solution, although this one does not work in chrome:  Add 'localhost.test' and 'auth.localhost.test' at the end of 127.0.0.1 localhost in /etc/hosts and `# morbo -v appname -l http//localhost.test:3000`.  now, http://localhost.test:3000/ works just fine with safari, firefox, and the Mojolicious test agent (but not chrome).

Using dnsmasq is often an elegant solution for use-cases like this.
Make sure that the DNS server provided by dnsmasq on localhost is the primary DNS server on your computer (e.g., by editing /etc/resolv.conf and prepending "nameserver 127.0.0.1").
Then, add an entry like "address=/sylspace.dev/127.0.0.1" to "/etc/dnsmasq.conf" and every host / subdomain in that domain is automatically resolved to localhost.

heiko

Justin Hawkins

unread,
May 30, 2017, 8:12:40 AM5/30/17
to 'sri' via Mojolicious

On 29 May 2017, at 8:55 am, iaw4 <ivo...@gmail.com> wrote:

thanks, heiko.  my site relies heavily on proper handling many host subdomains.    for example, my auth subdomain handles OAuth intereactions with google, which are subdomain specific.  and then each of my users has their own vanity subdomain, but they nicely share session information.  once logged into one subdomain, they can go to another.  so, for my case, the usual testing just within sites (get_ok('/')) is insufficient.  I really do need to work with full http:// and URLs to obtain the subdomain and make different decisions based on it.  I guess my app is unusual :-(.

To do this, take the decision logic (which parses the hostname), and make it testable. For instance, make it check an environment variable first:

my $domain;
if ($ENV{OVERRIDE_DOMAIN}) {
  $domain = $ENV{OVERRIDE_DOMAIN};
}
else {
  $domain = $self->req.., # normal logic
}

Then you can go back to using the built in testing idioms, and simply set the environment variable where appropriate.

Cheers,

Justin
Reply all
Reply to author
Forward
0 new messages