Beefy Boxes and Bandwidth Generously Provided by pair Networks
Your skill will accomplish
what the force of many cannot
 
PerlMonks  

URI.pm bug or am i missing something?

by jeffa (Chancellor)
on Apr 19, 2003 at 16:10 UTC ( #251675=perlquestion: print w/ replies, xml ) Need Help??
jeffa has asked for the wisdom of the Perl Monks concerning the following question:

Several months ago i was playing with pulling form vars from URI's. The problem is handling multiple keys such as 'foo=bar&foo=baz'. I decided to use URI and was shocked to find that the following code:
use URI; use Data::Dumper; my $uri = URI->new('http://localhost/foo.cgi?foo=bar&foo=baz'); my %form_var = $uri->query_form; print Dumper \%form_var;
Yielded:

$VAR1 = {
          'foo' => 'baz'
        };
So i hunted down query_form() (it is located in URI/_query.pm) and discovered this at the end of that subroutine:
map { s/\+/ /g; uri_unescape($_) } map { /=/ ? split(/=/, $_, 2) : ($_ => '')} split(/&/, $old);
Then i decided to recode that with something like this:
my %hash; for my $pair (split /&/, $old) { my ($k,$v) = map { s/\+/ /g; uri_unescape($_) } split /=/, $pair, 2; if (exists $hash{$k}) { if (ref $hash{$k}) { push @{$hash{$k}}, $v; } else { $hash{$k} = [$hash{$k},$v]; } } else { $hash{$k} = $v; } } return %hash;
Now when i run my test code, i get the output i expect:

$VAR1 = {
          'foo' => [
                     'bar',
                     'baz'
                   ]
        };
The reason i am bringing this up is because i submitted this as a patch to Gisle Aas and never heard back. The bug has been 'resolved', but my test case is contrary ...

Is this really a 'bug' in URI or am i missing something? I really feel that query_form() should handle multiple values with the same key, but giving the lack of response i got from Mr. Aas, i can't help but think i am missing something ... thanks :) (oh, and i am not ruling out the possibility that my message never reached Mr. Aas. - i just want to be sure before i bug him again.)

jeffa

L-LL-L--L-LL-L--L-LL-L--
-R--R-RR-R--R-RR-R--R-RR
B--B--B--B--B--B--B--B--
H---H---H---H---H---H---
(the triplet paradiddle with high-hat)

Comment on URI.pm bug or am i missing something?
Select or Download Code
Re: URI.pm bug or am i missing something?
by Juerd (Abbot) on Apr 19, 2003 at 17:21 UTC

    I would call this not a bug, but lack of feature.

    Your way of handling is scary, though, because it means things are not what you expect them to be if there are multiple values with the same key. In PLP I chose to have both an array and a scalar for each name. With your example, you'd end up with something like:

    { 'foo' => 'baz', '@foo' => [ 'bar', 'baz' ] }

    Juerd
    - http://juerd.nl/
    - spamcollector_perlmonks@juerd.nl (do not use).
    

Re: URI.pm bug or am i missing something?
by demerphq (Chancellor) on Apr 19, 2003 at 17:56 UTC

    I just had a look through the RFC's and it doesnt seem clear how this should be handled, however it does seem clear that it should be properly handled as in at least one example in RFC 1866 where there are two values for the same key. And I think its also clear that the URI code is buggy. From what I understand it should handle ";" as well as "&". I would say follow up. Id be interested to hear what is said.


    ---
    demerphq

    <Elian> And I do take a kind of perverse pleasure in having an OO assembly language...
      I don't think the RFC needs to specify how it should be handled. It never says unique keys, so you can't assume key uniqueness.

      As for the other thing, it's been reported already ( 27 Query separator is hard-coded to be '&' on Thu Nov 8 22:04:14 2001 ).

        It never says unique keys, so you can't assume key uniqueness.

        Agreed, and my point goes further in that given that the spec doesnt specify how this should be handled, yet does contain an example that contains duplicate keys it seems reasonable to conclude that the spec meant to allow duplicate keys.


        ---
        demerphq

        <Elian> And I do take a kind of perverse pleasure in having an OO assembly language...
•Re: URI.pm bug or am i missing something?
by merlyn (Sage) on Apr 20, 2003 at 02:16 UTC
    But this shows that it's your code, not URI that is broken:
    use URI; my $uri = URI->new('http://localhost/foo.cgi?foo=bar&foo=baz'); my @result = $uri->query_form; print join(":", @result), "\n";
    This prints:
    foo:bar:foo:baz
    So the problem is your code. You are taking stuff that might have a duplicated key, and shoving it into a hash. Of course you lose data when you do that!

    -- Randal L. Schwartz, Perl hacker
    Be sure to read my standard disclaimer if this is a reply.

Re: URI.pm bug or am i missing something?
by hossman (Prior) on Apr 20, 2003 at 06:10 UTC

    As merlyn has pointed out, there isn't really a bug here, just some confusion about how to use the method. (Personally, I would consider this a documentation bug) The POD doesn't really say what it returns, just that...

    This method sets and returns query components that use the application/x-www-form-urlencoded format. Key/value pairs are separated by "&" and the key is separated from the value with a "=" character.

    It's easy to see how you could interpret that to mean that it returns a hash (which is what most people think of when they think of "pairs") ... but the truth is it accepts multiple key=>val pairs with the same key as input, and returns multiple key=>val pairs with the same key as output...

    laptop:~> perl -l -w -MURI my $u = new URI(); $u->query_form('foo'=>'bar','foo'=>'baz'); print join ':', $u->query_form; __END__ foo:bar:foo:baz

    ...when you slurp the output into a hash, you are ignoring all but one pair with the same key. As I said, I would consider this a documentation bug, because I don't think the POD is very clear, but the method is doing what it says.

    For future refrence, when I looked at the bug you filed, i noticed it was marked "Fixed in 1.22 added" .. so i took a look at the Changelog for that rev, which mentions the new addition of URI::QueryParam. Looking at the Docs for that module was very enlightening. Using it adds a lot of methods to URI objects that look closer to what you want...

    laptop:~> perl -l -w -MURI -MURI::QueryParam my $u = new URI('http://perl.com/?a=b&foo=baz&c=d&foo=bar'); print join ', ', $u->query_param('foo'); __END__ baz, bar

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://251675]
Approved by Corion
Front-paged by Mr_Person
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others meditating upon the Monastery: (4)
As of 2014-09-21 05:37 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    How do you remember the number of days in each month?











    Results (166 votes), past polls