You are viewing a plain text version of this content. The canonical link for it is here.
Posted to modperl@perl.apache.org by Jeff <mo...@aquabolt.com> on 2005/12/26 19:32:45 UTC

Apache2::Cookies - getting all names

Folks,

I am finding it hard to correctly interpret the Apache2::Cookie 
documentation: The docs say:
   @names = $j->cookies();        # all cookie names

When I do this, for the following cookies:
   c1 => 'v1',
   c2 => 'v2',

I expect @names to contain ( "c1", "c2" ), but instead
@names contains ( "c1", "c1=v1", "c2", "c2=v2" )

The following code has the above problem:

my $jar     =  Apache2::Cookie::Jar->new( $r );
my @names   = $jar->cookies;
for my $name ( @names ) {
   my $cookie = $jar->cookies( $name );
   my @vals = $cookie->value();
   print "cookie: $name values: @vals\n";
}


Instead, I have ended up with:

my $jar     =  Apache2::Cookie::Jar->new( $r )->cookies;
my @cookies = values %$jar;
for my $cookie ( @cookies ) {
   my $token = $cookie->name();
   my @vals = $cookie->value();
   print "cookie: $token value: @vals\n";
}


Is there a better way? I couldn't get this to work:

my @cookies = values /
   %{ scalar Apache2::Cookie::Jar->new( $r )->cookies };

- seems that the Jar class is trying much to hard to be clever? Or maybe 
I'm just being dumb?

Thoughts appreciated,

Jeff





Re: Apache2::Cookies - getting all names

Posted by Jeff <mo...@aquabolt.com>.
-------- Original Message --------
From: Juan Jose Natera Abreu <ju...@lunarpages.com>
To: Jeff <mo...@aquabolt.com>
CC: mod_perl List <mo...@perl.apache.org>
Subject: Re:Apache2::Cookies - getting all names
Date: 26/12/2005 19:35

> Hi,
> 
> How are you creating the cookies?
> 
> Apache2::Cookie has the same interface as CGI pm (a method that takes
> named parameters).
> 
>>When I do this, for the following cookies:
>>   c1 => 'v1',
>>   c2 => 'v2',
>>
> 
> Try this instead:
> 
> $c1 = Apache2::Cookie->new($r, -name  => 'c1', -value => 'v1');
> $c2 = Apache2::Cookie->new($r, -name  => 'c2', -value => 'v2');
> 

Thanks - but my question was not about how to create cookies.

My question was:-

Given:

   my $jar   =  Apache2::Cookie::Jar->new( $r ); # get the jar
   my @names = $jar->cookies();                  # all cookie names

Why does @names contain values that are not cookie names?

I am guessing that the docs are wrong on this one.

Regards,
Jeff



Re: Apache2::Cookies - getting all names

Posted by Juan Jose Natera Abreu <ju...@lunarpages.com>.
Hi,

How are you creating the cookies?

Apache2::Cookie has the same interface as CGI pm (a method that takes
named parameters).

> When I do this, for the following cookies:
>    c1 => 'v1',
>    c2 => 'v2',
> 

Try this instead:

$c1 = Apache2::Cookie->new($r, -name  => 'c1', -value => 'v1');
$c2 = Apache2::Cookie->new($r, -name  => 'c2', -value => 'v2');

Regards,


-- 
Juan Jose Natera Abreu <ju...@lunarpages.com>


Re: Apache2::Cookies - getting all names

Posted by Jeff Armstrong <mo...@aquabolt.com>.
-------- Original Message  --------
From: "Philip M. Gollucci" <pg...@p6m7g8.com>
To: Jeff <mo...@aquabolt.com>
Cc: mod_perl List <mo...@perl.apache.org>
Subject: Re:Apache2::Cookies - getting all names
Date: Wed Dec 28 2005 16:38:44

> Convesly, we could patch the code instead of the docs to make it do what 
> the docs said originally ?
> Index: Cookie.pm
> ===================================================================
> --- Cookie.pm   (revision 359541)
> +++ Cookie.pm   (working copy)
> @@ -40,7 +40,7 @@
>      my $jar = $req->jar or return;
>      $jar->cookie_class(__PACKAGE__);
>      return $jar->get(shift) if @_;
> -    return wantarray ? %$jar : $jar;
> +    return wantarray ? keys %$jar : $jar;
>  }
> 
> I'm betting the code change is what we want here.
> 

Oh lovely tied hashness :) I agree about the code change -  code posted 
by others shows that folks are coding round the bugette. Maybe what 
should really happen is:

my @names = $jar->names();
my @cookies = $jar->cookies();

Where the first returns the keys of %$jar and the second returns the 
values of %$jar. Unfortunately, this is not backwardly compatible :( - 
so how about something like:

my @names     = $jar->cookies();      # just the names
my @cookies   = $jar->all_cookies();  # all the cookies ie value %$jar
my @allnames  = $jar->all_names();    # all the names ie keys %$jar

and deprecate wantarray $jar->cookies() in favour of $jar->all_names()? 
I personally don't like that the return value of $jar->cookies() is 
sometimes cookie[s] and sometimes names and sometimes the jar itself.

In fact, the all_cookies() is what I really really want :) and have 
ended up coding. I want to know if I am suffering multi-same-named cookies!

Regards,
Jeff





Re: Apache2::Cookies - getting all names

Posted by "Philip M. Gollucci" <pg...@p6m7g8.com>.
Jeff wrote:
> Folks,
> 
> I am finding it hard to correctly interpret the Apache2::Cookie 
> documentation: The docs say:
>   @names = $j->cookies();        # all cookie names

The actual code (SVN-trunk), says this:

The final return line in sub fetch() below explains your findings.

package Apache2::Cookie::Jar;
sub cookies { Apache2::Cookie->fetch(@_) }

package Apache2::Cookie;
sub fetch {
     my $class = shift;
     my $req = shift;
     unless (defined $req) {
         my $usage = 'Usage: Apache2::Cookie->fetch($r): missing 
argument $r';
         $req = eval {Apache2::RequestUtil->request} or die <<EOD;
$usage: attempt to fetch global Apache2::RequestUtil->request failed: $@.
EOD
     }
     $req = APR::Request::Apache2->handle($req)
         unless $req->isa("APR::Request");

     my $jar = $req->jar or return;
     $jar->cookie_class(__PACKAGE__);
     return $jar->get(shift) if @_;
     return wantarray ? %$jar : $jar;
}

 >Given:
 >
 >  my $jar   =  Apache2::Cookie::Jar->new( $r ); # get the jar
 >  my @names = $jar->cookies();                  # all cookie names
 >
 >Why does @names contain values that are not cookie names?
 >
 >I am guessing that the docs are wrong on this one.

You are correct, I'll update them:
[Move this disccustion to apreq-dev (at) perl (dot) apache (dot) org  CC'ed]

How about like so?

Index: Cookie.pm
===================================================================
--- Cookie.pm   (revision 359541)
+++ Cookie.pm   (working copy)
@@ -191,14 +191,14 @@
  internal I<cookies> table in C<apreq_jar_t>, so their impact will
  be noticed by all libapreq2 applications during this request.

-In list context C<< $jar->cookies() >> returns the list of names
+In list context C<< $jar->cookies() >> returns the list of cookies
  for all the cookies in the jar.  The order corresponds to the
  order in which the cookies appeared in the incoming "Cookie" header.

  This method will throw an C<< APR::Request::Error >> object into $@ if
  the returned value(s) could be unreliable.  In particular, note that
  C<< scalar $jar->cookies("foo") >> will not croak if it can locate
-the a "foo" cookie within the jar's parsed cookie table, even if the
+a "foo" cookie within the jar's parsed cookie table, even if the
  cookie parser has failed (the cookies are parsed in the same order
  as they appeared in the "Cookie" header). In all other circumstances
  C<cookies> will croak if the parser failed to successfully parse the
@@ -209,11 +209,12 @@

      $cookie = $j->cookies("foo");  # first foo cookie
      @cookies = $j->cookies("foo"); # all foo cookies
-    @names = $j->cookies();        # all cookie names
+    @names = $j->cookies();        # all cookies
+    $hashref = $j->cookies();      # hashref keyed on cookie name
+                                   # of all cookies



-
  =head2 status

      $jar->status()

Convesly, we could patch the code instead of the docs to make it do what 
the docs said originally ?
Index: Cookie.pm
===================================================================
--- Cookie.pm   (revision 359541)
+++ Cookie.pm   (working copy)
@@ -40,7 +40,7 @@
      my $jar = $req->jar or return;
      $jar->cookie_class(__PACKAGE__);
      return $jar->get(shift) if @_;
-    return wantarray ? %$jar : $jar;
+    return wantarray ? keys %$jar : $jar;
  }

I'm betting the code change is what we want here.




-- 
------------------------------------------------------------------------
"Love is not the one you can picture yourself marrying,
but the one you can't picture the rest of your life without."

"It takes a minute to have a crush on someone, an hour to like someone,
and a day to love someone, but it takes a lifetime to forget someone..."

Philip M. Gollucci (pgollucci@p6m7g8.com) 301.254.5198
Consultant / http://p6m7g8.net/Resume/resume.shtml
Senior Software Engineer - TicketMaster - http://ticketmaster.com


Re: Apache2::Cookies - getting all names

Posted by Jeff <mo...@aquabolt.com>.
-------- Original Message --------
From: Jonathan <jv...@2xlp.com>
To: Jeff <mo...@aquabolt.com>
CC: mod_perl List <mo...@perl.apache.org>
Subject: Re:Apache2::Cookies - getting all names
Date: 26/12/2005 19:19

> 
> This is what I do:
> 
>     my $cookiejar     = Apache2::Cookie::Jar->new( 
> $this->{'ApacheRequest'} );
>     my @names         = $cookiejar->cookies();
>     DEBUG_COOKIE >0 &&  print STDERR "-| Found These Cookies : " . 
> (join  " , ",@names) . "\n";
>     if ( $cookiejar->cookies( $this->{'CookieDefaults'}->{'names'}-> 
> {'Session'} ) )
>     {
>         DEBUG_COOKIE >0 && print STDERR "-|  Handling cookie: {$this-> 
> {'CookieDefaults'}->{'names'}->{'Session'}} \n";
>         DEBUG_COOKIE >0 && print STDERR "-|    >> Validating... \n";
>         my     %c_cookies = Apache2::Cookie->fetch( 
> $this->{'ApacheRequest'} );
>         my     $c_value = $c_cookies{ 
> $this->{'CookieDefaults'}->{'names'}-> {'Session'} }->value;
>         DEBUG_COOKIE >0 && print STDERR "-|       \%c_cookies => \{\} ; 
> \ $c_cookies\{{$this->{'CookieDefaults'}->{'names'}->{'Session'}}\}- 
>  >value = '", $c_value , "'\n";
>         DEBUG_COOKIE >0 && print STDERR "-|       Validating c_value  
> $c_value \n";
>     }   
> 

Thanks for the code, interesting, but doesn't answer the question about 
invalid @names - I guess that your debug message also lists out names 
that don't actually exist in the jar?

> 
> you've got
>     my @vals = $cookie->value();
> 
> as far as i know, cookies only have a single scalar value. you'll  need 
> to serialize/deserialize any other data structure into it.
> 

The docs state that a cookie can have multiple values, and I have tested 
and confirmed this. Ditto multiple cookies with the same name!

Run the following cookies through your code - I think you will find that 
you miss the second value on the first cookie, and not see the second 
cookie at all:

# -------------------------
# Calling page created two cookies with the same name,
# and each cookie contains multiple values
# Create multiple cookies with same name and multiple values
my $c1 = Apache2::Cookie->new($r,
   -name    =>  'my_session',
   -value   =>  ['session1', $r->mtime(), ],
   -expires =>  '+365d',
   -domain  =>  '127.0.0.1',
   -path    =>  '/',
   -secure  =>  0,
);
$c1->bake($r);

my $c2 = Apache2::Cookie->new($r,
   -name    =>  'my_session',
   -value   =>  ['session2', $r->mtime(), ],
   -expires =>  '+365d',
   -domain  =>  '127.0.0.1',
   -path    =>  '/',
   -secure  =>  0,
);
$c1->bake($r);

# ----------------------------
# In the receiving page... list all the cookies/values
my $jar     =  Apache2::Cookie::Jar->new( $r )->cookies;
my @cookies = values %$jar;
print "<pre>\n";
for my $cookie ( @cookies ) {
   my $name = $cookie->name();
   my @vals = $cookie->value();
   print "cookie: $name     value: @vals\n";
}
print "</pre>\n";


 From this behaviour, it seems that $jar is a class presenting as a tied 
hash - but hey, that's ok, as values %$jar gets em all!

Any other examples of cookie infra appreciated.

Regards & thanks,

Jeff

Re: Apache2::Cookies - getting all names

Posted by Jonathan <jv...@2xlp.com>.
This is what I do:

	my $cookiejar 	= Apache2::Cookie::Jar->new( $this->{'ApacheRequest'} );
	my @names 		= $cookiejar->cookies();
	DEBUG_COOKIE >0 &&  print STDERR "-| Found These Cookies : " . (join  
" , ",@names) . "\n";
	if ( $cookiejar->cookies( $this->{'CookieDefaults'}->{'names'}-> 
{'Session'} ) )
	{
		DEBUG_COOKIE >0 && print STDERR "-|  Handling cookie: {$this-> 
{'CookieDefaults'}->{'names'}->{'Session'}} \n";
		DEBUG_COOKIE >0 && print STDERR "-|    >> Validating... \n";
		my 	%c_cookies = Apache2::Cookie->fetch( $this->{'ApacheRequest'} );
		my 	$c_value = $c_cookies{ $this->{'CookieDefaults'}->{'names'}-> 
{'Session'} }->value;
		DEBUG_COOKIE >0 && print STDERR "-|       \%c_cookies => \{\} ; \ 
$c_cookies\{{$this->{'CookieDefaults'}->{'names'}->{'Session'}}\}- 
 >value = '", $c_value , "'\n";
		DEBUG_COOKIE >0 && print STDERR "-|       Validating c_value  
$c_value \n";
	}	



you've got
	my @vals = $cookie->value();

as far as i know, cookies only have a single scalar value. you'll  
need to serialize/deserialize any other data structure into it.

cookiedefaults are something that i set in a sitewide configuration  
file:

my $CookieDefaults = 	{
				domain 			=> 	
				[
					'127.0.0.1',
					'dev.2xlp.com',
				],
				path 			=> '/',
				expires 		=> '+365d',
				secure 			=> 0,
				names 			=>
				{
					'Session' => 'my_session',
					'AutoLogin' => 'my_autologin',
				}
			};


and i have a session wrapper class that sets/reads cookies for all  
domains in the cookie defaults configuration, for the Session cookie  
( named names[Session] ) or AutoLogin cookie ( names[AutoLogin] )

that setup is very manageable for me



On Dec 26, 2005, at 1:32 PM, Jeff wrote:

> Folks,
>
> I am finding it hard to correctly interpret the Apache2::Cookie  
> documentation: The docs say:
>   @names = $j->cookies();        # all cookie names
>
> When I do this, for the following cookies:
>   c1 => 'v1',
>   c2 => 'v2',
>
> I expect @names to contain ( "c1", "c2" ), but instead
> @names contains ( "c1", "c1=v1", "c2", "c2=v2" )
>
> The following code has the above problem:
>
> my $jar     =  Apache2::Cookie::Jar->new( $r );
> my @names   = $jar->cookies;
> for my $name ( @names ) {
>   my $cookie = $jar->cookies( $name );
>   my @vals = $cookie->value();
>   print "cookie: $name values: @vals\n";
> }
>
>
> Instead, I have ended up with:
>
> my $jar     =  Apache2::Cookie::Jar->new( $r )->cookies;
> my @cookies = values %$jar;
> for my $cookie ( @cookies ) {
>   my $token = $cookie->name();
>   my @vals = $cookie->value();
>   print "cookie: $token value: @vals\n";
> }
>
>
> Is there a better way? I couldn't get this to work:
>
> my @cookies = values /
>   %{ scalar Apache2::Cookie::Jar->new( $r )->cookies };
>
> - seems that the Jar class is trying much to hard to be clever? Or  
> maybe I'm just being dumb?
>
> Thoughts appreciated,
>
> Jeff
>
>
>
>


Re: Apache2::Cookies - getting all names

Posted by Enno <bu...@xs4all.nl>.
I use this:

use Apache2::Cookie;

sub get_cookies($) {

    my $r = shift;

    my $jar = Apache2::Cookie::Jar->new($r);

    my $cookies = $jar->cookies();

    return $cookies;
}

and call any cookie with

$cookies->{key}->value if $cookies->{key}->value;

please note that you need a new libapreq2, I had huge issues with 2.06 and
had to switch to the svn trunk to get it to work properly.
not sure if those fixes already made it to the current devel package,
though, but it might be wise to upgrade if you are unsure.

(one of the probs was that it would segfault if you tried to set an empty
cookie).

Enno


>    c1 => 'v1',
>    c2 => 'v2',
>
> I expect @names to contain ( "c1", "c2" ), but instead
> @names contains ( "c1", "c1=v1", "c2", "c2=v2" )
>
> The following code has the above problem:
>
> my $jar     =  Apache2::Cookie::Jar->new( $r );
> my @names   = $jar->cookies;
> for my $name ( @names ) {
>    my $cookie = $jar->cookies( $name );
>    my @vals = $cookie->value();
>    print "cookie: $name values: @vals\n";
> }
>
>
> Instead, I have ended up with:
>
> my $jar     =  Apache2::Cookie::Jar->new( $r )->cookies;
> my @cookies = values %$jar;
> for my $cookie ( @cookies ) {
>    my $token = $cookie->name();
>    my @vals = $cookie->value();
>    print "cookie: $token value: @vals\n";
> }
>
>
> Is there a better way? I couldn't get this to work:
>
> my @cookies = values /
>    %{ scalar Apache2::Cookie::Jar->new( $r )->cookies };
>
> - seems that the Jar class is trying much to hard to be clever? Or maybe
> I'm just being dumb?
>
> Thoughts appreciated,
>
> Jeff
>
>
>
>
>