Intermittent 400's using Mojo::UserAgent

75 views
Skip to first unread message

Todd

unread,
Mar 10, 2017, 5:12:43 PM3/10/17
to Mojolicious
Hi,

Writing a client for a REST api that I created.  The client works approximately half the time.  Here's a simple version that can recreate the problem:

#!/usr/bin/env perl

use v5.18;
use strict;
use warnings;
use Mojo::UserAgent;
use MIME::Base64;
use Data::Dumper;

my $ua   = Mojo::UserAgent->new();
my $user = "scot-alerts";
my $pass = "xxxx";
my $auth = "Basic ".encode_base64($user.":".$pass);

$ua->on( start => sub {
    my $ua = shift;
    my $tx = shift;
    $tx->req->headers->header(
        'Authorization' => $auth
    );
});

my $results = {};
for my $i (1..100) {

    my $tx = $ua->get(
        'https://myservername/myapp/api/v2/event/1' => {Accept => '*/*' }
    );

    my $code = $tx->res->code;
    $results->{$code}++;

}
say Dumper($results);

Three runs of the above yield:
$VAR1 = {
          '200' => 49,
          '400' => 51
        };
$VAR1 = {
          '200' => 50,
          '400' => 50
        };
$VAR1 = {
          '400' => 55,
          '200' => 45
        };

I'm not sure if the problem is with Apache Config or Client.  Web browser access to https://myservername/scot/api/v2/event/1 never fails.
I do see the following in the apache2 error log:

AH02031: Hostname myservername provided via SNI, but no hostname provided in HTTP request

I've tried adding the "Host" header (set to myservername) when I set the "Authorization" header, but that didn't change anything.

System is Ubuntu 14.04, Apache/2.4.7 (Ubuntu), Perl 5.18.2, up to date Mojo::UserAgent  (cpanm claims it is up to date anyway)

Any ideas what I'm doing wrong?  Thanks!
Todd



Todd

unread,
Mar 10, 2017, 5:31:22 PM3/10/17
to Mojolicious
In case it wasn't clear from above:

client sample above -----> apache -------> mojolicious app 

where the apache is configured as a reverse proxy to the mojolicious app.
The apache server also provided the authentication check.

the apache stanza that configures this setup:

<VirtualHost *:443>
    ServerName myservername

    ProxyPreserveHost   On
    ProxyPass           /   http://localhost:3000/ keepalive=On retry=0
    ProxyPassReverse    /   http://localhost:3000/

-snip- 


Stefan Adams

unread,
Mar 10, 2017, 6:26:52 PM3/10/17
to mojolicious

On Fri, Mar 10, 2017 at 4:12 PM, Todd <todd....@gmail.com> wrote:
my $auth = "Basic ".encode_base64($user.":".$pass);

I don't know why, but try this:

chomp(my $auth = "Basic ".encode_base64($user.":".$pass));

Sebastian Riedel

unread,
Mar 10, 2017, 7:59:03 PM3/10/17
to mojol...@googlegroups.com
MOJO_USERAGENT_DEBUG=1

--
Sebastian Riedel
http://mojolicio.us
http://github.com/kraih
http://twitter.com/kraih

Stefan Adams

unread,
Mar 10, 2017, 9:55:12 PM3/10/17
to mojolicious

On Fri, Mar 10, 2017 at 6:59 PM, Sebastian Riedel <kra...@gmail.com> wrote:
MOJO_USERAGENT_DEBUG=1

Is it due to the random ordering of the headers?  It's successful when Authorization: Basic with it's improper \n is the last of the headers...?

Todd

unread,
Mar 13, 2017, 12:03:01 PM3/13/17
to Mojolicious
That did fixed it.  Thank you!

Joel Berger

unread,
Mar 14, 2017, 9:46:41 AM3/14/17
to Mojolicious
While this answer may work, it isn't the truly correct answer. By default, encode_base64 adds linebreaks to the result. You don't want those and this is why chomp seems to work, but it won't if the text should ever become long enough to be on two lines. What you want (mentioned obliquely here: http://mojolicious.org/perldoc/Mojo/Util#b64_encode) is to use encode_base64 (or b64_encode) with an empty string as the second parameter.

All that said, you don't even need to do this manually. If you add your username and password to the request url Mojo::UserAgent will just build this header for you. See the example here: http://mojolicious.org/perldoc/Mojo/UserAgent#SYNOPSIS

Cheers,
Joel

Stefan Adams

unread,
Mar 14, 2017, 9:50:21 AM3/14/17
to mojolicious
Ah, thank you, Joel! What great info!!

--
You received this message because you are subscribed to the Google Groups "Mojolicious" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mojolicious+unsubscribe@googlegroups.com.
To post to this group, send email to mojol...@googlegroups.com.
Visit this group at https://groups.google.com/group/mojolicious.
For more options, visit https://groups.google.com/d/optout.

Charlie Brady

unread,
Mar 16, 2017, 1:30:32 PM3/16/17
to Mojolicious

On Tue, 14 Mar 2017, Joel Berger wrote:

> All that said, you don't even need to do this manually. If you add your
> username and password to the request url Mojo::UserAgent will just build
> this header for you. See the example
> here: http://mojolicious.org/perldoc/Mojo/UserAgent#SYNOPSIS

Note however that you shouldn't do this:

my $value =
$ua->get("https://$user:$pa...@example.com/test.json")->result->json;

if your password might contain @. You will find part of your password
leaking out via DNS lookups.

I think:

Mojo::URL->new('https://example.com/test.json')->username($user)->password($pass)

is safe.
Reply all
Reply to author
Forward
0 new messages