OpenSource++

While hacking on some OX based controller code today I got an unsuspected error when parsing a POST request.

Can't use an undefined value as an ARRAY reference
at local/lib/perl5/Web/Request.pm line 426.

Huh.

As my usage of Web::Request seemed to be correct, I opened local/lib/perl5/Web/Request.pm and looked at the code around line 426:

423: my $ret = { %{ $self->all_query_parameters } };
424: my $body_parameters = $self->all_body_parameters;
425: for my $key (keys %$body_parameters) {
426:     push @{ $ret->{$key} ||= [] }, @{ $body_parameters->{key} };
427: }

The error was easy to spot: $body_parameters->{key} should be $body_parameters->{$key} (notice the $ in front of key).

So I changed that (in my local copy). And my code worked! Yay!

But - being a good open source citizen - before committing my fix I also wanted to add a test case. This turned out to be a bit harder...

A POST Web::Request

The problem was that the bug was only triggered by x-www-form-urlencoded POST requests. Obviously the test suite did not contain such a request (else the problem would have been spotted earlier). And I had no idea how to generate such a request using Web::Request.

After a bit of acking the source (which by now I cloned on github and checked out to my machine) and looking at code and tests of related modules, I figured out that I had to pass the payload as an IO::Handle like object and set the correct HTTP headers.

Here's one way I came up with:

use IO::String;
my $payload="foo=bar&foo=baz&bar=bar";
my $io = IO::String->new($payload);
$req = Web::Request->new_from_env({
    'REQUEST_METHOD'    => 'POST',
    'SCRIPT_NAME'       => '/foo',
    'CONTENT_LENGTH'    => length($payload),
    'CONTENT_TYPE'      => "application/x-www-form-urlencoded",
    'psgi.input'        => $io,
});

I added this to an existing test file that seemed to test similar features. And send off the pull request.

As i figured that would take a while until my patch was reviewed & hopefully accepted, I added a fixed method to our subclass of Web::Request. So I could continue hacking on my controller, which I happily did.

The Awesomeness of Open Source

After coming back from an evening run I checked my emails, only to find a short message from Jesse Luehrs (who is the maintainer of Web::Request) telling me that he already merged my code. Yay!

Not only that, but he also pushed a new release to CPAN. Double-Yay!

And the moral of it is

It's easy to contribute! If you find a bug, at least report it, or better yet, fix it. Or at least try to come up with a failing test case.

It's very likely that your patch will be accepted, earning you not only working code (and thus less needs for hacky workarounds in your code base ( = more bugs)) but eternal fame and endless gratitude!