Re: [PATCH] FIFO header order support in HTTP::Headers

Michael Greb <[email protected]>
Newsgroups gmane.comp.lang.perl.modules.lwp
Message-ID <[email protected]>
On Sep 5, 2008, at 7:23 PM, Gisle Aas wrote:
> True; and in this case we need to define what happens when fields are
> modified with 'push', 'set' or 'init' and 'remove' as that's the API
> that modify stuff.  Let me suggest the following definition of the
> behaviour:
>
> - 'push' always append the field at the end of all headers.  multiple
> occurrences of a field name do not have to be consecutive.
>
> - 'init' either does nothing or it works like 'push'.
>
> - 'remove' will always remove all concurrences of a field.
>
> - 'set' will work like 'push' if no other occurrence of the field  
> exists.
>
> - 'set' will update the first occurrence if the field exists (and
> remove all other occurrences).  if multiple field values is provided
> with 'set' they are basically all injected at the location of the
> first existing value.


On Sep 6, 2008 at 2:57 AM, Gisle Aas wrong:
> I think it makes sense to be able to enable them separately.
> Suggested interface:
>
>  $h->scan(\&cb, original_order => 1, original_case => 1);
>  $h->as_string(eol => "\n", original_order => 1, original_case => 1);'

The attached patch uses the interface above and works towards the  
behavior outlined in the first message.  Due to the headers being  
stored as a hash, pushing does not currently preserve previous values,  
second and subsequent pushes of the same header will overwrite the  
previous value.  Supporting this would require a change in how the  
headers are stored within the module.  Your thoughts?  The most  
obvious solution to me would be storing headers and their values as a  
hashref in an arrayref

Server: Fool/1.0
content-encoding: gzip
Content-Type: text/plain; charset="UTF-8"
Content-Encoding: base64
Date: Fri Sep  5 10:24:37 CEST 2008

Would be stored as (assuming push_header):

$self->{_headers} = [
	{ server => 'Fool/1.0' },
	{ content-encoding => 'gzip'},
	{ content-type => 'text/plain; charset="UTF-8"},
	{ content-encoding => 'base64' },
	{ date => 'Fri Sep  5 10:24:37 CEST 2008' }
];

This would negate the need for $self->{_original_order}.  $self- 
 >{_header} (or some such) could be a hashref with header fields as  
the keys and the header's index(s) in _headers as their value to speed  
and simplify direct access to an individual header's value.

--
Michael Greb
Linode.com
609-593-7103 ext 1205
0001-preservation-of-original-header-order-and-case.patch (application/octet-stream, 2.2 KB)
From 2fd608a131e40375719bd79f6b427890a5db7529 Mon Sep 17 00:00:00 2001
From: Michael Greb <[email protected]>
Date: Sun, 7 Sep 2008 07:33:59 -0400
Subject: [PATCH] preservation of original header order and case

---
 lib/HTTP/Headers.pm |   17 ++++++++++-------
 1 files changed, 10 insertions(+), 7 deletions(-)

diff --git a/lib/HTTP/Headers.pm b/lib/HTTP/Headers.pm
index 5eb5329..c7d37dd 100644
--- a/lib/HTTP/Headers.pm
+++ b/lib/HTTP/Headers.pm
@@ -82,7 +82,7 @@ sub header
     my %seen;
     while (@_) {
 	my $field = shift;
-        my $op = @_ ? ($seen{lc($field)}++ ? 'PUSH' : 'SET') : 'GET';
+        my $op = @_ ? 'SET': 'GET';
 	@old = $self->_header($field, shift, $op);
     }
     return @old if wantarray;
@@ -117,9 +117,12 @@ sub remove_header
     my $field;
     my @values;
     foreach $field (@fields) {
-	$field =~ tr/_/-/ if $field !~ /^:/ && $TRANSLATE_UNDERSCORE;
-	my $v = delete $self->{lc $field};
-	push(@values, ref($v) eq 'ARRAY' ? @$v : $v) if defined $v;
+        $field =~ tr/_/-/ if $field !~ /^:/ && $TRANSLATE_UNDERSCORE;
+        $field = lc $field if $field !~ /^:/;
+        my $v = delete $self->{$field};
+        delete $self->{_original_case}{$field};
+        @{$self->{_original_order}} = grep !/^\Q$field\E$/, @{$self->{_original_order}};
+        push(@values, ref($v) eq 'ARRAY' ? @$v : $v) if defined $v;
     }
     return @values;
 }
@@ -167,7 +170,7 @@ sub _header
     $op ||= defined($val) ? 'SET' : 'GET';
     unless ($op eq 'GET' || ($op eq 'INIT' && @old)) {
         if (defined($val)) {
-            my @new = ($op eq 'PUSH') ? @old : ();
+            my @new = ($op eq 'SET') ? @old : ();
             if (ref($val) ne 'ARRAY') {
                 push(@new, $val);
             }
@@ -176,12 +179,12 @@ sub _header
             }
             $self->{$field} = @new > 1 ? \@new : $new[0];
             push @{$self->{_original_order}}, $field
-                if ($op eq 'PUSH' || !@old);
+                unless ($op eq 'SET' && @old);
         }
         elsif ($op ne 'PUSH') {
             delete $self->{$field};
             @{$self->{_original_order}} =
-                grep !/\Q$field\E/, @{$self->{_original_order}};
+                grep !/^\Q$field\E$/, @{$self->{_original_order}};
         }
     }
     @old;
-- 
1.5.5.3
PGP.sig (application/pgp-signature, 186 B) - not displayed
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.