Hello,

Here is a little test suite that shows what the documentation for
HTTP::Headers led me to expect from the header() method in scalar and
list context.

Here's the relevant excerpt from the documentation:

    The $value argument may be a plain string or a reference to an
    array of strings for a multi-valued field. If the $value is unde-
    fined or not given, then that header field will remain unchanged.

    The old value (or values) of the last of the header fields is
    returned.  If no such field exists "undef" will be returned.

    A multi-valued field will be retuned as separate values in list
    context and will be concatenated with ", " as separator in scalar
    context.  The HTTP spec (RFC 2616) promise that joining multiple
    values in this way will not change the semantic of a header field,
    but in practice there are cases like old-style Netscape cookies
    (see HTTP::Cookies) where "," is used as part of the syntax of a
    single field value.

    Examples:

     $header->header(MIME_Version => '1.0',
                     User_Agent   => 'My-Web-Client/0.01');
     $header->header(Accept => "text/html, text/plain, image/*");
     $header->header(Accept => [qw(text/html text/plain image/*)]);
     @accepts = $header->header('Accept');  # get multiple values
     $accepts = $header->header('Accept');  # get values as a single string


I wrote the following test suite to test it:

    use Test::More tests => 8;
    
    use HTTP::Headers;
    my $header = HTTP::Headers->new;
    
    #
    # these are the example in HTTP::Headers
    #
    $header = HTTP::Headers->new;
    $header->header( Accept => [qw(text/html text/plain image/*)] );
    
    # get multiple values
    @accepts = $header->header('Accept');    
    is_deeply( [EMAIL PROTECTED], [ "text/html", "text/plain", "image/*" ], "List 
context");
    
    # get values as a single string
    $accepts = $header->header('Accept');    
    is( $accepts, "text/html, text/plain, image/*", "Scalar context" );
    
    
    #
    # another initialisation
    #
    $header->header( Accept => "text/html, text/plain, image/*" );
    
    # get multiple values
    @accepts = $header->header('Accept');    
    is_deeply( [EMAIL PROTECTED], [ "text/html", "text/plain", "image/*" ], "List 
context");
    
    # get values as a single string
    $accepts = $header->header('Accept');    
    is( $accepts, "text/html, text/plain, image/*", "Scalar context" );
    
    #
    # yet another initialisation
    #
    $header = HTTP::Headers->new;
    $header->push_header( 'Accept' => $_ ) 
      for qw( text/html text/plain image/* );
    
    # get multiple values
    @accepts = $header->header('Accept');    
    is_deeply( [EMAIL PROTECTED], [ "text/html", "text/plain", "image/*" ], "List 
context");
    
    # get values as a single string
    $accepts = $header->header('Accept');    
    is( $accepts, "text/html, text/plain, image/*", "Scalar context" );
    
    #
    # yet another initialisation
    #
    $header = HTTP::Headers->new;
    $header->push_header( 'Accept' => "text/html, text/plain, image/*" );
    
    # get multiple values
    @accepts = $header->header('Accept');    
    is_deeply( [EMAIL PROTECTED], [ "text/html", "text/plain", "image/*" ], "List 
context");
    
    # get values as a single string
    $accepts = $header->header('Accept');    
    is( $accepts, "text/html, text/plain, image/*", "Scalar context" );

But it fails:

    1..8
    ok 1 - List context
    ok 2 - Scalar context
    not ok 3 - List context
    #     Failed test (headers at line 28)
    #     Structures begin differing at:
    #          $got->[0] = 'text/html, text/plain, image/*'
    #     $expected->[0] = 'text/html'
    ok 4 - Scalar context
    ok 5 - List context
    ok 6 - Scalar context
    not ok 7 - List context
    #     Failed test (headers at line 57)
    #     Structures begin differing at:
    #          $got->[0] = 'text/html, text/plain, image/*'
    #     $expected->[0] = 'text/html'
    ok 8 - Scalar context
    # Looks like you failed 2 tests of 8.

My conclusion is that HTTP::Headers does not have a consistent behaviour
(it depends on how the HTTP::Headers object was updated). I think it
might be volontary, because of the following lines in the documentation:

    in practice there are cases like old-style Netscape cookies
    (see HTTP::Cookies) where "," is used as part of the syntax of a
    single field value.

It might not be relevant to normal LWP::UserAgent/HTTP::Daemon usage,
because of the way HTTP::Request and HTTP::Response objects are
actually created by LWP::UserAgent and HTTP::Daemon. I might not
have looked as deeply in the code as I should have.

I also tried to write two different patches, but they were not good enough.
There was a naive one (using split /\s*,\s*/), and a more enlightened one
(using HTTP::Headers::Util::split_header_words), but both did break the
libwww test suite at some point.

So, in the end, I'm just pointing at this "problem", asking if it's a
bug or not.


-- 
 Philippe "BooK" Bruhat                                       <[EMAIL PROTECTED]>

 The truly stupid always find a way to create disaster.
                                                (Moral from Groo #10 (Image))

Reply via email to