Skip to content

Commit

Permalink
expires needs to be an attribute
Browse files Browse the repository at this point in the history
  • Loading branch information
kraih committed Feb 11, 2015
1 parent 79ee42a commit b542059
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 106 deletions.
3 changes: 2 additions & 1 deletion Changes
@@ -1,5 +1,6 @@

5.78 2015-02-10
5.78 2015-02-11
- Replaced expires method in Mojo::Cookie::Response with an attribute.
- Added split_cookie_header function to Mojo::Util.
- Improved design of built-in templates.
- Fixed bug in Mojo::DOM that made parsing a requirement.
Expand Down
4 changes: 2 additions & 2 deletions lib/Mojo/Cookie/Request.pm
Expand Up @@ -7,7 +7,7 @@ sub parse {
my ($self, $str) = @_;

my @cookies;
my @pairs = map {@$_} @{split_header($str // '')};
my @pairs = map {@$_} @{split_header $str // ''};
while (@pairs) {
my ($name, $value) = (shift @pairs, shift @pairs);
next if $name =~ /^\$/;
Expand All @@ -21,7 +21,7 @@ sub to_string {
my $self = shift;
return '' unless length(my $name = $self->name // '');
my $value = $self->value // '';
return join '=', $name, $value =~ /[,;" ]/ ? quote($value) : $value;
return join '=', $name, $value =~ /[,;" ]/ ? quote $value : $value;
}

1;
Expand Down
44 changes: 16 additions & 28 deletions lib/Mojo/Cookie/Response.pm
Expand Up @@ -4,27 +4,15 @@ use Mojo::Base 'Mojo::Cookie';
use Mojo::Date;
use Mojo::Util qw(quote split_cookie_header);

has [qw(domain httponly max_age origin path secure)];
has [qw(domain expires httponly max_age origin path secure)];

my %ATTRS = map { $_ => 1 } qw(expires domain path secure max-age httponly);

sub expires {
my $self = shift;

# Upgrade
my $e = $self->{expires};
return $self->{expires} = defined $e && !ref $e ? Mojo::Date->new($e) : $e
unless @_;
$self->{expires} = shift;

return $self;
}
my %ATTRS = map { $_ => 1 } qw(domain expires httponly max-age path secure);

sub parse {
my ($self, $str) = @_;

my @cookies;
my $tree = split_cookie_header($str // '');
my $tree = split_cookie_header $str // '';
while (my $pairs = shift @$tree) {
push @cookies,
$self->new(name => shift(@$pairs), value => shift(@$pairs) // '');
Expand All @@ -33,9 +21,9 @@ sub parse {
my ($name, $value) = (shift @$pairs, shift @$pairs);

next unless $ATTRS{my $attr = lc $name};
$attr = 'max_age' if $attr eq 'max-age';
$cookies[-1]
->$attr($attr eq 'secure' || $attr eq 'httponly' ? 1 : $value);
$value = Mojo::Date->new($value)->epoch if $attr eq 'expires';
$cookies[-1]{$attr eq 'max-age' ? 'max_age' : $attr}
= $attr eq 'secure' || $attr eq 'httponly' ? 1 : $value;
}
}

Expand All @@ -48,10 +36,11 @@ sub to_string {
# Name and value
return '' unless length(my $name = $self->name // '');
my $value = $self->value // '';
my $cookie = join '=', $name, $value =~ /[,;" ]/ ? quote($value) : $value;
my $cookie = join '=', $name, $value =~ /[,;" ]/ ? quote $value : $value;

# "expires"
if (defined(my $e = $self->expires)) { $cookie .= "; expires=$e" }
my $expires = $self->expires;
if (defined $expires) { $cookie .= '; expires=' . Mojo::Date->new($expires) }

# "domain"
if (my $domain = $self->domain) { $cookie .= "; domain=$domain" }
Expand Down Expand Up @@ -105,6 +94,13 @@ implements the following new ones.
Cookie domain.
=head2 expires
my $expires = $cookie->expires;
$cookie = $cookie->expires(time + 60);
Expiration for cookie.
=head2 httponly
my $bool = $cookie->httponly;
Expand Down Expand Up @@ -147,14 +143,6 @@ connections.
L<Mojo::Cookie::Response> inherits all methods from L<Mojo::Cookie> and
implements the following new ones.
=head2 expires
my $expires = $cookie->expires;
$cookie = $cookie->expires(time + 60);
$cookie = $cookie->expires(Mojo::Date->new(time + 60));
Expiration for cookie.
=head2 parse
my $cookies = Mojo::Cookie::Response->parse('f=b; path=/');
Expand Down
3 changes: 1 addition & 2 deletions lib/Mojo/UserAgent/CookieJar.pm
Expand Up @@ -77,8 +77,7 @@ sub find {
next unless $cookie->domain || $host eq $cookie->origin;

# Check if cookie has expired
my $expires = $cookie->expires;
next if $expires && time > ($expires->epoch || 0);
if (my $expires = $cookie->expires) { next if time > ($expires || 0) }
push @$new, $cookie;

# Taste cookie
Expand Down
121 changes: 49 additions & 72 deletions t/mojo/cookie.t
Expand Up @@ -174,25 +174,22 @@ is_deeply(Mojo::Cookie::Response->parse, [], 'no cookies');
# Parse response cookie (Netscape)
$cookies = Mojo::Cookie::Response->parse(
'CUSTOMER=WILE_E_COYOTE; path=/; expires=Tuesday, 09-Nov-1999 23:12:40 GMT');
is $cookies->[0]->name, 'CUSTOMER', 'right name';
is $cookies->[0]->value, 'WILE_E_COYOTE', 'right value';
is $cookies->[0]->expires, 'Tue, 09 Nov 1999 23:12:40 GMT',
'right expires value';
is $cookies->[0]->name, 'CUSTOMER', 'right name';
is $cookies->[0]->value, 'WILE_E_COYOTE', 'right value';
is $cookies->[0]->expires, 942189160, 'right expires value';
is $cookies->[1], undef, 'no more cookies';

# Parse multiple response cookies (Netscape)
$cookies
= Mojo::Cookie::Response->parse(
'CUSTOMER=WILE_E_COYOTE; expires=Tuesday, 09-Nov-1999 23:12:40 GMT; path=/'
. ',SHIPPING=FEDEX; path=/; expires=Tuesday, 09-Nov-1999 23:12:41 GMT');
is $cookies->[0]->name, 'CUSTOMER', 'right name';
is $cookies->[0]->value, 'WILE_E_COYOTE', 'right value';
is $cookies->[0]->expires, 'Tue, 09 Nov 1999 23:12:40 GMT',
'right expires value';
is $cookies->[1]->name, 'SHIPPING', 'right name';
is $cookies->[1]->value, 'FEDEX', 'right value';
is $cookies->[1]->expires, 'Tue, 09 Nov 1999 23:12:41 GMT',
'right expires value';
is $cookies->[0]->name, 'CUSTOMER', 'right name';
is $cookies->[0]->value, 'WILE_E_COYOTE', 'right value';
is $cookies->[0]->expires, 942189160, 'right expires value';
is $cookies->[1]->name, 'SHIPPING', 'right name';
is $cookies->[1]->value, 'FEDEX', 'right value';
is $cookies->[1]->expires, 942189161, 'right expires value';
is $cookies->[2], undef, 'no more cookies';

# Parse response cookie (RFC 6265)
Expand All @@ -205,9 +202,8 @@ is $cookies->[0]->value, 'ba r', 'right value';
is $cookies->[0]->domain, 'example.com', 'right domain';
is $cookies->[0]->path, '/test', 'right path';
is $cookies->[0]->max_age, 60, 'right max age value';
is $cookies->[0]->expires, 'Thu, 07 Aug 2008 07:07:59 GMT',
'right expires value';
is $cookies->[0]->secure, 1, 'right secure flag';
is $cookies->[0]->expires, 1218092879, 'right expires value';
is $cookies->[0]->secure, 1, 'right secure flag';
is $cookies->[1], undef, 'no more cookies';

# Parse response cookie with invalid flag (RFC 6265)
Expand All @@ -220,9 +216,8 @@ is $cookies->[0]->value, 'ba r', 'right value';
is $cookies->[0]->domain, 'example.com', 'right domain';
is $cookies->[0]->path, '/test', 'right path';
is $cookies->[0]->max_age, 60, 'right max age value';
is $cookies->[0]->expires, 'Thu, 07 Aug 2008 07:07:59 GMT',
'right expires value';
is $cookies->[0]->secure, undef, 'no secure flag';
is $cookies->[0]->expires, 1218092879, 'right expires value';
is $cookies->[0]->secure, undef, 'no secure flag';
is $cookies->[1], undef, 'no more cookies';

# Parse quoted response cookie (RFC 6265)
Expand All @@ -235,9 +230,8 @@ is $cookies->[0]->value, 'b a" r"\\', 'right value';
is $cookies->[0]->domain, 'example.com', 'right domain';
is $cookies->[0]->path, '/test', 'right path';
is $cookies->[0]->max_age, 60, 'right max age value';
is $cookies->[0]->expires, 'Thu, 07 Aug 2008 07:07:59 GMT',
'right expires value';
is $cookies->[0]->secure, 1, 'right secure flag';
is $cookies->[0]->expires, 1218092879, 'right expires value';
is $cookies->[0]->secure, 1, 'right secure flag';
is $cookies->[1], undef, 'no more cookies';

# Parse quoted response cookie (RFC 6265, alternative)
Expand All @@ -250,9 +244,8 @@ is $cookies->[0]->value, 'b a" ;r"\\', 'right value';
is $cookies->[0]->domain, 'example.com', 'right domain';
is $cookies->[0]->path, '/test', 'right path';
is $cookies->[0]->max_age, 60, 'right max age value';
is $cookies->[0]->expires, 'Thu, 07 Aug 2008 07:07:59 GMT',
'right expires value';
is $cookies->[0]->secure, 1, 'right secure flag';
is $cookies->[0]->expires, 1218092879, 'right expires value';
is $cookies->[0]->secure, 1, 'right secure flag';
is $cookies->[1], undef, 'no more cookies';

# Parse quoted response cookie roundtrip (RFC 6265)
Expand All @@ -265,19 +258,17 @@ is $cookies->[0]->value, 'b ,a";= r"\\', 'right value';
is $cookies->[0]->domain, 'example.com', 'right domain';
is $cookies->[0]->path, '/test', 'right path';
is $cookies->[0]->max_age, 60, 'right max age value';
is $cookies->[0]->expires, 'Thu, 07 Aug 2008 07:07:59 GMT',
'right expires value';
is $cookies->[0]->secure, 1, 'right secure flag';
is $cookies->[0]->expires, 1218092879, 'right expires value';
is $cookies->[0]->secure, 1, 'right secure flag';
is $cookies->[1], undef, 'no more cookies';
$cookies = Mojo::Cookie::Response->parse($cookies->[0]);
is $cookies->[0]->name, 'foo', 'right name';
is $cookies->[0]->value, 'b ,a";= r"\\', 'right value';
is $cookies->[0]->domain, 'example.com', 'right domain';
is $cookies->[0]->path, '/test', 'right path';
is $cookies->[0]->max_age, 60, 'right max age value';
is $cookies->[0]->expires, 'Thu, 07 Aug 2008 07:07:59 GMT',
'right expires value';
is $cookies->[0]->secure, 1, 'right secure flag';
is $cookies->[0]->expires, 1218092879, 'right expires value';
is $cookies->[0]->secure, 1, 'right secure flag';
is $cookies->[1], undef, 'no more cookies';

# Parse quoted response cookie roundtrip (RFC 6265, alternative)
Expand All @@ -290,19 +281,17 @@ is $cookies->[0]->value, 'b ,a" r"\\', 'right value';
is $cookies->[0]->domain, 'example.com', 'right domain';
is $cookies->[0]->path, '/test', 'right path';
is $cookies->[0]->max_age, 60, 'right max age value';
is $cookies->[0]->expires, 'Thu, 07 Aug 2008 07:07:59 GMT',
'right expires value';
is $cookies->[0]->secure, 1, 'right secure flag';
is $cookies->[0]->expires, 1218092879, 'right expires value';
is $cookies->[0]->secure, 1, 'right secure flag';
is $cookies->[1], undef, 'no more cookies';
$cookies = Mojo::Cookie::Response->parse($cookies->[0]);
is $cookies->[0]->name, 'foo', 'right name';
is $cookies->[0]->value, 'b ,a" r"\\', 'right value';
is $cookies->[0]->domain, 'example.com', 'right domain';
is $cookies->[0]->path, '/test', 'right path';
is $cookies->[0]->max_age, 60, 'right max age value';
is $cookies->[0]->expires, 'Thu, 07 Aug 2008 07:07:59 GMT',
'right expires value';
is $cookies->[0]->secure, 1, 'right secure flag';
is $cookies->[0]->expires, 1218092879, 'right expires value';
is $cookies->[0]->secure, 1, 'right secure flag';
is $cookies->[1], undef, 'no more cookies';

# Parse quoted response cookie roundtrip (RFC 6265, another alternative)
Expand All @@ -315,19 +304,17 @@ is $cookies->[0]->value, 'b ;a" r"\\', 'right value';
is $cookies->[0]->domain, 'example.com', 'right domain';
is $cookies->[0]->path, '/test', 'right path';
is $cookies->[0]->max_age, 60, 'right max age value';
is $cookies->[0]->expires, 'Thu, 07 Aug 2008 07:07:59 GMT',
'right expires value';
is $cookies->[0]->secure, 1, 'right secure flag';
is $cookies->[0]->expires, 1218092879, 'right expires value';
is $cookies->[0]->secure, 1, 'right secure flag';
is $cookies->[1], undef, 'no more cookies';
$cookies = Mojo::Cookie::Response->parse($cookies->[0]);
is $cookies->[0]->name, 'foo', 'right name';
is $cookies->[0]->value, 'b ;a" r"\\', 'right value';
is $cookies->[0]->domain, 'example.com', 'right domain';
is $cookies->[0]->path, '/test', 'right path';
is $cookies->[0]->max_age, 60, 'right max age value';
is $cookies->[0]->expires, 'Thu, 07 Aug 2008 07:07:59 GMT',
'right expires value';
is $cookies->[0]->secure, 1, 'right secure flag';
is $cookies->[0]->expires, 1218092879, 'right expires value';
is $cookies->[0]->secure, 1, 'right secure flag';
is $cookies->[1], undef, 'no more cookies';

# Parse quoted response cookie roundtrip (RFC 6265, yet another alternative)
Expand All @@ -340,19 +327,17 @@ is $cookies->[0]->value, '"b a" r"', 'right value';
is $cookies->[0]->domain, 'example.com', 'right domain';
is $cookies->[0]->path, '/test', 'right path';
is $cookies->[0]->max_age, 60, 'right max age value';
is $cookies->[0]->expires, 'Thu, 07 Aug 2008 07:07:59 GMT',
'right expires value';
is $cookies->[0]->secure, 1, 'right secure flag';
is $cookies->[0]->expires, 1218092879, 'right expires value';
is $cookies->[0]->secure, 1, 'right secure flag';
is $cookies->[1], undef, 'no more cookies';
$cookies = Mojo::Cookie::Response->parse($cookies->[0]);
is $cookies->[0]->name, 'foo', 'right name';
is $cookies->[0]->value, '"b a" r"', 'right value';
is $cookies->[0]->domain, 'example.com', 'right domain';
is $cookies->[0]->path, '/test', 'right path';
is $cookies->[0]->max_age, 60, 'right max age value';
is $cookies->[0]->expires, 'Thu, 07 Aug 2008 07:07:59 GMT',
'right expires value';
is $cookies->[0]->secure, 1, 'right secure flag';
is $cookies->[0]->expires, 1218092879, 'right expires value';
is $cookies->[0]->secure, 1, 'right secure flag';
is $cookies->[1], undef, 'no more cookies';

# Parse response cookie without value (RFC 2965)
Expand All @@ -365,9 +350,8 @@ is $cookies->[0]->value, '', 'no value';
is $cookies->[0]->domain, 'example.com', 'right domain';
is $cookies->[0]->path, '/test', 'right path';
is $cookies->[0]->max_age, 60, 'right max age value';
is $cookies->[0]->expires, 'Thu, 07 Aug 2008 07:07:59 GMT',
'right expires value';
is $cookies->[0]->secure, 1, 'right secure flag';
is $cookies->[0]->expires, 1218092879, 'right expires value';
is $cookies->[0]->secure, 1, 'right secure flag';
is $cookies->[0]->to_string,
'foo=; expires=Thu, 07 Aug 2008 07:07:59 GMT; domain=example.com;'
. ' path=/test; secure; Max-Age=60', 'right result';
Expand All @@ -381,9 +365,8 @@ is $cookies->[0]->value, '', 'no value';
is $cookies->[0]->domain, 'example.com', 'right domain';
is $cookies->[0]->path, '/test', 'right path';
is $cookies->[0]->max_age, 60, 'right max age value';
is $cookies->[0]->expires, 'Thu, 07 Aug 2008 07:07:59 GMT',
'right expires value';
is $cookies->[0]->secure, 1, 'right secure flag';
is $cookies->[0]->expires, 1218092879, 'right expires value';
is $cookies->[0]->secure, 1, 'right secure flag';
is $cookies->[0]->to_string,
'foo=; expires=Thu, 07 Aug 2008 07:07:59 GMT; domain=example.com;'
. ' path=/test; secure; Max-Age=60', 'right result';
Expand Down Expand Up @@ -420,32 +403,26 @@ is $cookies->[0]->value, 'bar', 'right value';
is $cookies->[0]->domain, 'example.com', 'right domain';
is $cookies->[0]->path, '/', 'right path';
is $cookies->[0]->max_age, 0, 'right max age value';
is $cookies->[0]->expires, 'Thu, 01 Jan 1970 00:00:00 GMT',
'right expires value';
is $cookies->[0]->expires->epoch, 0, 'right expires epoch value';
is $cookies->[0]->secure, 1, 'right secure flag';
is $cookies->[0]->expires, 0, 'right expires value';
is $cookies->[0]->secure, 1, 'right secure flag';
is $cookies->[1], undef, 'no more cookies';

# Parse response cookie with two digit year (RFC 6265)
$cookies = Mojo::Cookie::Response->parse(
'foo=bar; Path=/; Expires=Saturday, 09-Nov-19 23:12:40 GMT; Secure');
is $cookies->[0]->name, 'foo', 'right name';
is $cookies->[0]->value, 'bar', 'right value';
is $cookies->[0]->path, '/', 'right path';
is $cookies->[0]->expires, 'Sat, 09 Nov 2019 23:12:40 GMT',
'right expires value';
is $cookies->[0]->expires->epoch, 1573341160, 'right expires epoch value';
is $cookies->[0]->secure, 1, 'right secure flag';
is $cookies->[0]->name, 'foo', 'right name';
is $cookies->[0]->value, 'bar', 'right value';
is $cookies->[0]->path, '/', 'right path';
is $cookies->[0]->expires, 1573341160, 'right expires value';
is $cookies->[0]->secure, 1, 'right secure flag';
is $cookies->[1], undef, 'no more cookies';
$cookies = Mojo::Cookie::Response->parse(
'foo=bar; Path=/; Expires=Tuesday, 09-Nov-99 23:12:40 GMT; Secure');
is $cookies->[0]->name, 'foo', 'right name';
is $cookies->[0]->value, 'bar', 'right value';
is $cookies->[0]->path, '/', 'right path';
is $cookies->[0]->expires, 'Tue, 09 Nov 1999 23:12:40 GMT',
'right expires value';
is $cookies->[0]->expires->epoch, 942189160, 'right expires epoch value';
is $cookies->[0]->secure, 1, 'right secure flag';
is $cookies->[0]->name, 'foo', 'right name';
is $cookies->[0]->value, 'bar', 'right value';
is $cookies->[0]->path, '/', 'right path';
is $cookies->[0]->expires, 942189160, 'right expires value';
is $cookies->[0]->secure, 1, 'right secure flag';
is $cookies->[1], undef, 'no more cookies';

# Abstract methods
Expand Down
2 changes: 1 addition & 1 deletion t/mojolicious/group_lite_app.t
Expand Up @@ -314,7 +314,7 @@ $t->app->secrets(['test2', 'test1']);
$t->get_ok('/bridge2stash' => {'X-Flash2' => 1})->status_is(200)
->content_is(
"stash too!cookie!!signed_cookie!!bad_cookie--12345678!session!!\n");
ok $t->tx->res->cookie('mojolicious')->expires->epoch < time,
ok $t->tx->res->cookie('mojolicious')->expires < time,
'session cookie expires';

# With cookies and session cleared (rotating secrets)
Expand Down

0 comments on commit b542059

Please sign in to comment.